<?php
// 后台首页
namespace control;

// 启用扩展类
require_once 'interface.php';

// 系统管理后台基类
class adIndexClass
{
    /*属性*/
    public $powerAll = "";                        //系统权限目录
    public $powerAllLang = "";                        //系统权限目录当前语言
    public array $control;                                  //当前登录者
    public array $controlJob;                               //当前登录者职位
    public array $controlPower = [];                        //当前登录者权限
    public string $warn;                                     //提示

    public static $user = []; //用户
    public static $stid;
    public static $staff = [];
    public static $warehouse = [];
    public static $publicSettings = [];
    public string $root;
    public static string $coid;
    public const baseUnit = 100;//金额以分为单位是将除以此基础值
    public static string $unit = '元';
    use interfaces;

    /*构造函数*/
    public function __construct()
    {
        // 启用扩展
        $this->init();
        //获得全局函数
        $this->powerAll     = $GLOBALS['powerAll'];
        $this->powerAllLang = $_SESSION['lang'] == 'SC' ? $GLOBALS['powerAll'] : $GLOBALS['powerAll' . $_SESSION['lang']];
        $this->root         = root;

        // 用于接口调用后端函数
        if (!empty($this->header['Auth']) || strpos($_SERVER['REQUEST_URI'], '/control') === false) {
            return;
        }

        //登录验证
        if (empty($_SESSION['stid'])) {
            $this->warn = L('adIndex.index.Nologin');
        } elseif ($this->get('cla') == "login" and $this->get('fun') == "out") {
            unset($_SESSION['stid']);
            $_SESSION['warn'] = L('adIndex.index.DroppedOut');
            header("Location:{$this->root}control/adIndex.html?cla=login");
            exit();
        } else {
            $this->control = query("staff", "stid = '$_SESSION[stid]'");
            if ($this->control['stid'] != $_SESSION['stid']) {
                $this->warn = L('adIndex.index.AccountNotFound');
            } else {
                self::$stid = $this->control['stid'];
                self::$user = query('user', " stid = '" . self::$stid . "' ");
                // 登录限制
                if ($_SESSION['deviceId'] != self::$user['deviceId'] && para('adLoginMultiDeviceLimit') == '开') {
                    unset($_SESSION['stid'], $_SESSION['deviceId']);
                    $_SESSION['warn'] = L('adIndex.index.OffsiteLogin');
                    exit("<script>top.location.href = root+'control/adIndex.html?cla=login'</script>");
                }
                $this->controlJob   = query("job", " id = '" . $this->control['jobId'] . "' ");
                self::$staff        = $this->control;
                $this->controlPower = self::getUserPower();
                //设置coid
                self::$coid = self::findCoid();
                //查询管理的仓库
                $condition       = $this->power('warehouse', 'seeAll') ? "" : " and member like '%" . self::$stid . "%' ";
                $warehouse       = find(['table' => 'warehouse', 'field' => 'id', 'where' => " coid = '" . self::$coid . "' {$condition} "]);
                self::$warehouse = static::isNull($warehouse['array']) ? [] : array_column($warehouse['array'], 'id');
                //获取公共选项设置
                self::$publicSettings = self::findOptionSetting();
                $loginPage            = static::rGet(self::$user['uid'] . 'loginPage');
                $company              = query('company', "coid = '" . self::$coid . "'");
                //判断当前请求页面是否是在账套中，是则使用账套中的单位,否则使用参数中的单位
                self::$unit = $company['unit'] ?: para('moneyUnit');
                //语言包
                if (empty($_SESSION['lang'])) {
                    $where            = [
                        'type' => '系统语言',
                        'stid' => static::$stid,
                    ];
                    $info             = query('user_setting', generateWhere($where));
                    $_SESSION['lang'] = $info['value'] ?: 'SC';
                }
                if ($loginPage == 1) {
                    //登录成功时检查是否设置了默认值
                    $this->insertDefault();
                    //给用户设置默认查看的统计图表设置
                    $this->setDefaultSetting();
                    static::rSet(self::$user['uid'] . 'loginPage', 0);
                }
            }
        }
    }


    /**
     * 生成默认值
     */
    public function insertDefault()
    {
        //生成默认仓库分类
        if (static::total(array('table' => 'warehouse_type', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            //默认档案分类
            static::insert(array(
                'table' => 'warehouse_type',
                'field' => [
                    'id'   => self::getId(),
                    'coid' => self::$coid,
                    'name' => '默认分类',
                    'pid'  => 0,
                    'list' => 1,
                ],
            ));
        }
        //生成本位币
        if (static::total(array('table' => 'currency', 'where' => "isBase = '是' and coid = '" . self::$coid . "'")) == 0) {
            static::insert(array(
                'table' => 'currency',
                'field' => [
                    'id'     => self::getId(),
                    'coid'   => self::$coid,
                    'name'   => '人民币',
                    'isBase' => '是',
                    'code'   => 'CNY',
                    'rate'   => 1,
                ],
            ));
        }
        //判断当前超级管理员是否有人才库信息，没有则生成一个，不然不能更新管理员信息
        $userAll = find(array('table' => 'user', 'where' => "isDel = 1"));
        foreach ($userAll['array'] as $array) {
            $staff = query('staff', "stid = '$array[stid]'");
            if (static::total(array('table' => 'talent_pool', 'where' => "id = '$staff[talentId]'")) == 0) {
                $talentId = self::getId();
                static::insert(array(
                    'table' => 'talent_pool',
                    'field' => [
                        'id'       => $talentId,
                        'name'     => $staff['name'],
                        'tel'      => $staff['tel'],
                        'state'    => '人才登记',
                        'workFlow' => 2,
                    ],
                ));
                static::update(
                    array('table' => 'staff', 'field' => ['talentId' => $talentId], 'where' => "stid = '$staff[stid]'")
                );
            }
        }
        //生成默认档案库位
        if (static::total(array('table' => 'archive_cabinet', 'where' => "isDefault = 1")) == 0) {
            //默认档案库位
            static::insert(array(
                'table' => 'archive_cabinet',
                'field' => [
                    'id'        => self::getId(),
                    'name'      => '默认库位',
                    'isDefault' => 1,
                    'list'      => 1,
                ],
            ));
        }
//        生成默认档案分类
        if (static::total(array('table' => 'archive_type', 'where' => "isDefault = 1")) == 0) {
            //默认档案分类
            static::insert(array(
                'table' => 'archive_type',
                'field' => [
                    'id'        => self::getId(),
                    'name'      => '默认分类',
                    'isDefault' => 1,
                    'list'      => 1,
                ],
            ));
        }
        if (static::total(array('table' => 'pool', 'where' => "coid = '" . self::$coid . "' and type='线索池' and isDefault =1")) == 0) {
            //默认线索池
            static::insert(array(
                'table' => 'pool',
                'field' => [
                    'id'          => suiji(),
                    'type'        => '线索池',
                    'name'        => '默认线索池',
                    'manager'     => 'Ore126054470Vd',
                    'isCooper'    => 1,
                    'isSee'       => 0,
                    'maxNum'      => 0,
                    'frequency'   => 0,
                    'limitMinute' => -1,
                    'recycling'   => -1,
                    'remindDay'   => 0,
                    'isDefault'   => 1,
                    'stid'        => 'Ore126054470Vd',
                ],
            ));
        }
        if (static::total(array('table' => 'pool', 'where' => "coid = '" . self::$coid . "' and type='公客池' and isDefault =1")) == 0) {
            //默认公客池
            static::insert(array(
                'table' => 'pool',
                'field' => [
                    'id'          => suiji(),
                    'coid'        => self::$coid,
                    'type'        => '公客池',
                    'name'        => '默认客户池',
                    'manager'     => 'Ore126054470Vd',
                    'isCooper'    => 1,
                    'isSee'       => 0,
                    'maxNum'      => 0,
                    'frequency'   => 0,
                    'limitMinute' => -1,
                    'recycling'   => -1,
                    'remindDay'   => 0,
                    'isDefault'   => 1,
                    'stid'        => 'Ore126054470Vd',
                ],
            ));
        }
        $accountRule = companyClass::returnRule(1);
        //生成初始科目
        if (static::total(array('table' => 'subject', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            $all = find(array('table' => 'subject_demo', 'where' => "level = 1 and accountRule = '$accountRule' order by list asc"));
            foreach ($all['array'] as $array) {
                $id = suiji();
                static::insert(array(
                    'table' => 'subject',
                    'field' => [
                        'id'                 => $id,
                        'coid'               => self::$coid,
                        'type'               => $array['type'],
                        'code'               => $array['code'],
                        'name'               => $array['name'],
                        'direction'          => $array['direction'],
                        'pid'                => '0',
                        'state'              => $array['state'],
                        'numAccount'         => $array['numAccount'],
                        'assistAccount'      => $array['assistAccount'],
                        'currencyAccount'    => $array['currencyAccount'],
                        'numAccountText'     => $array['numAccountText'],
                        'assistAccountIds'   => $array['assistAccountIds'],
                        'currencyAccountIds' => $array['currencyAccountIds'],
                        'subjectSign'        => $array['subjectSign'],
                        'list'               => $array['list'],
                        'selfIndex'          => $array['selfIndex'],
                        'level'              => $array['level'],
                        'pinyin'             => $array['pinyin'],
                        'isDel'              => 0,
                    ],
                ));
                $this->insertSubjectChild($array['id'], $id, $accountRule);
            }
        }

        //生成现金流量表
        if (static::total(array('table' => 'cash', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            $all = find(array('table' => 'cash_demo', 'where' => "accountRule='$accountRule' order by code asc"));
            foreach ($all['array'] as $array) {
                static::insert(array(
                    'table' => 'cash',
                    'field' => [
                        'id'     => suiji(),
                        'coid'   => self::$coid,
                        'code'   => $array['code'],
                        'pinyin' => $array['pinyin'],
                        'name'   => $array['name'],
                        'type'   => $array['type'],
                        'text'   => $array['text'],
                    ],
                ));
            }
        }

        //生成凭证字
        if (static::total(array('table' => 'voucher_word', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            $all = find(array('table' => 'voucher_word_demo', 'where' => "1=1 order by time asc"));
            foreach ($all['array'] as $array) {
                static::insert(array(
                    'table' => 'voucher_word',
                    'field' => [
                        'id'        => suiji(),
                        'coid'      => self::$coid,
                        'word'      => $array['word'],
                        'title'     => $array['title'],
                        'isDefault' => $array['isDefault'],
                        'isDel'     => $array['isDel'],
                    ],
                ));
            }
        }


        $all = find(array('table' => 'asset_debt_formula', 'where' => "coid = '" . self::$coid . "'  order by list asc"));
        foreach ($all['array'] as $array) {
            $subject = query('subject', "id = '$array[subjectId]'");
            if (empty($subject['id'])) {
                delete(array('table' => 'asset_debt_formula', 'where' => "coid = '" . self::$coid . "'"));
                delete(array('table' => 'asset_debt', 'where' => "coid = '" . self::$coid . "'"));
                delete(array('table' => 'profit_income_formula', 'where' => "coid = '" . self::$coid . "'"));
                delete(array('table' => 'profit_income', 'where' => "coid = '" . self::$coid . "'"));
                break;
            }
        }
        //生成资产负债表
        if (static::total(array('table' => 'asset_debt', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            $all = find(array('table' => 'asset_debt_demo', 'where' => "accountRule='$accountRule' order by list asc"));
            foreach ($all['array'] as $array) {
                static::insert(array(
                    'table' => 'asset_debt',
                    'field' => [
                        'id'        => suiji(),
                        'coid'      => self::$coid,
                        'type'      => $array['type'],
                        'name'      => $array['name'],
                        'pid'       => $array['pid'],
                        'direction' => $array['direction'],
                        'list'      => $array['list'],
                    ],
                ));
            }
            $all = find(array('table' => 'asset_debt_formula_demo', 'where' => "accountRule='$accountRule' order by list asc"));
            foreach ($all['array'] as $array) {
                $subject = query('subject', "coid = '" . self::$coid . "' and code = '$array[subjectCode]'");
                static::insert(array(
                    'table' => 'asset_debt_formula',
                    'field' => [
                        'id'        => suiji(),
                        'coid'      => self::$coid,
                        'name'      => $array['name'],
                        'symbol'    => $array['symbol'],
                        'subjectId' => $subject['id'],
                        'rule'      => $array['rule'],
                    ],
                ));
            }
        }

        //生成利润表
        if (static::total(array('table' => 'profit_income', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            $all = find(array('table' => 'profit_income_demo', 'where' => "accountRule='$accountRule' order by list asc"));
            foreach ($all['array'] as $array) {
                static::insert(array(
                    'table' => 'profit_income',
                    'field' => [
                        'id'    => suiji(),
                        'coid'  => self::$coid,
                        'title' => $array['title'],
                        'type'  => $array['type'],
                        'name'  => $array['name'],
                        'pid'   => $array['pid'],
                    ],
                ));
            }
            $all = find(array('table' => 'profit_income_formula_demo', 'where' => "accountRule='$accountRule'"));
            foreach ($all['array'] as $array) {
                $subject = query('subject', "coid = '" . self::$coid . "' and code = '$array[subjectCode]'");
                static::insert(array(
                    'table' => 'profit_income_formula',
                    'field' => [
                        'id'        => suiji(),
                        'coid'      => self::$coid,
                        'name'      => $array['name'],
                        'symbol'    => $array['symbol'],
                        'subjectId' => $subject['id'],
                        'rule'      => $array['rule'],
                    ],
                ));
            }
        }

        if (static::total(array('table' => 'period_end_setting', 'where' => "coid = '" . self::$coid . "'")) == 0) {
            //生成预设凭证模板
            $all = find(array('table' => 'period_end_setting_demo', 'where' => " 1=1 order by list asc")); //accountRule='$accountRule'
            foreach ($all['array'] as $array) {
                $id           = suiji();
                $voucher_word = query('voucher_word', "coid = '" . self::$coid . "' and word = '$array[voucherWord]'");
                static::insert(array(
                    'table' => 'period_end_setting',
                    'field' => [
                        'id'            => $id,
                        'coid'          => self::$coid,
                        'name'          => $array['name'],
                        'type'          => $array['type'],
                        'voucherWord'   => $array['voucherWord'],
                        'voucherWordId' => $voucher_word['id'],
                        'para'          => $array['para'],
                        'isDel'         => 0,
                    ],
                ));
                $children = find(array('table' => 'period_end_setting_detail_demo', 'where' => "orderId = '$array[id]' order by list asc"));//and accountRule='$accountRule'
                foreach ($children['array'] as $item) {
                    $childSubject = query('subject', "coid = '" . self::$coid . "'  and code = '" . $item['subjectCode'] . "'");
                    static::insert(array(
                        'table' => 'period_end_setting_detail',
                        'field' => [
                            'id'        => suiji(),
                            'coid'      => self::$coid,
                            'orderId'   => $id,
                            'summary'   => $item['summary'],
                            'subjectId' => $childSubject['id'],
                            'rule'      => $item['rule'],
                            'direction' => $item['direction'],
                        ],
                    ));
                }
            }
        }
        $company = query('company', "coid = '" . self::$coid . "'");
        //生成预设会计电子档案文件夹
        if (static::total(array('table' => 'account_elect_file', 'where' => "coid = '" . self::$coid . "' and name = '财务归档'")) == 0) {
            $folderId = suiji();
            static::insert(array(
                'table' => 'account_elect_file',
                'field' => [
                    'id'   => $folderId,
                    'pid'  => '1',
                    'coid' => self::$coid,
                    'type' => 'folder',
                    'name' => '财务归档',
                    'stid' => self::$stid,
                ],
            ));
            static::insert(array(
                'table' => 'account_elect_file',
                'field' => [
                    'id'   => suiji(),
                    'pid'  => $folderId,
                    'coid' => self::$coid,
                    'type' => 'folder',
                    'name' => $company['name'],
                    'stid' => self::$stid,
                ],
            ));
        }
        //生成默认的账户
        if (static::total(array('table' => 'account', 'where' => "coid = '" . self::$coid . "' and type = '现金'")) == 0) {
            $currency = query('currency', "coid = '" . self::$coid . "' and isBase = '是'");
            $subject  = query('subject', "coid = '" . self::$coid . "' and code = '1001'");
            //默认的现金账户
            static::insert(array(
                'table' => 'account',
                'field' => [
                    'id'         => self::getId(),
                    'coid'       => self::$coid,
                    'name'       => '现金',
                    'type'       => '现金',
                    'orderNo'    => self::generateNo([
                        'prefix' => 'A',
                        'table'  => 'account',
                        'field'  => 'orderNo',
                        'where'  => "and coid = '" . self::$coid . "'",
                    ]),
                    'currencyId' => $currency['id'],
                    'subjectId'  => $subject['id'],
                    'initMoney'  => 0,
                    'stid'       => self::$stid,
                    'state'      => '启用',
                ],
            ));
        }
        if (static::total(array('table' => 'account', 'where' => "coid = '" . self::$coid . "' and type = '银行存款'")) == 0) {
            $currency = query('currency', "coid = '" . self::$coid . "' and isBase = '是'");
            $subject  = query('subject', "coid = '" . self::$coid . "' and code = '1002'");
            //默认的现金账户
            static::insert(array(
                'table' => 'account',
                'field' => [
                    'id'         => self::getId(),
                    'coid'       => self::$coid,
                    'name'       => '中国工商银行',
                    'type'       => '银行存款',
                    'orderNo'    => self::generateNo([
                        'prefix' => 'A',
                        'table'  => 'account',
                        'field'  => 'orderNo',
                        'where'  => "and coid = '" . self::$coid . "'",
                    ]),
                    'currencyId' => $currency['id'],
                    'subjectId'  => $subject['id'],
                    'initMoney'  => 0,
                    'stid'       => self::$stid,
                    'state'      => '启用',
                ],
            ));
        }
    }

    /**
     * 生成子科目
     */
    private function insertSubjectChild($pid, $newId, $accountRule)
    {
        $all = find(array('table' => 'subject_demo', 'where' => "pid = '$pid' and accountRule = '$accountRule' order by selfIndex"));
        foreach ($all['array'] as $array) {
            $id = suiji();
            static::insert(array(
                'table' => 'subject',
                'field' => [
                    'id'                 => $id,
                    'coid'               => self::$coid,
                    'type'               => $array['type'],
                    'code'               => $array['code'],
                    'name'               => $array['name'],
                    'direction'          => $array['direction'],
                    'pid'                => $newId,
                    'state'              => $array['state'],
                    'numAccount'         => $array['numAccount'],
                    'assistAccount'      => $array['assistAccount'],
                    'currencyAccount'    => $array['currencyAccount'],
                    'numAccountText'     => $array['numAccountText'],
                    'assistAccountIds'   => $array['assistAccountIds'],
                    'currencyAccountIds' => $array['currencyAccountIds'],
                    'pinyin'             => $array['pinyin'],
                    'list'               => $array['list'],
                    'selfIndex'          => $array['selfIndex'],
                    'level'              => $array['level'],
                    'isDel'              => 0,
                ],
            ));
            $this->insertSubjectChild($array['id'], $id, $accountRule);
        }
    }

    /**
     * 给个人用户设置默认设置
     */
    public function setDefaultSetting()
    {
        //生成凭证选项设置
        if (static::total(array('table' => 'user_setting', 'where' => "stid = '" . self::$stid . "' and coid='" . self::$coid . "' and type = '凭证设置'")
            ) == 0) {
            insert(array(
                'table' => 'user_setting',
                'field' => [
                    'coid'  => self::$coid,
                    'stid'  => self::$stid,
                    'type'  => '凭证设置',
                    'value' => json_encode(['voucherNumAdd' => '否', 'fixDate' => '否', 'fixDateValue' => ''], 320),
                ],
            ));
        }
        //生成OA小程序销售设置
        if (static::total(array('table' => 'user_setting', 'where' => "stid = '" . self::$stid . "'  and type = 'OA通知设置'")
            ) == 0) {
            insert(array(
                'table' => 'user_setting',
                'field' => [
                    'stid'  => self::$stid,
                    'type'  => 'OA通知设置',
                    'value' => json_encode(['message' => 1], 320),
                ],
            ));
        }

        //判断是否有销售过程统计设置
        if (static::total(array('table' => 'user_setting', 'where' => "stid = '" . self::$stid . "' and coid='" . self::$coid . "' and type = '销售过程统计'")
            ) == 0) {
            insert(array(
                'table' => 'user_setting',
                'field' => [
                    'coid'  => self::$coid,
                    'stid'  => self::$stid,
                    'type'  => '销售过程统计',
                    'value' => json_encode(
                        ["board", "follow_client", "sale_funnel", "follow_type", "follow_rank", "visit_rank"],
                        320
                    ),
                ],
            ));
        }
        //判断是否有销售业绩统计设置
        if (static::total(array('table' => 'user_setting', 'where' => "stid = '" . self::$stid . "' and coid='" . self::$coid . "' and type = '销售业绩统计'")
            ) == 0) {
            insert(array(
                'table' => 'user_setting',
                'field' => [
                    'coid'  => self::$coid,
                    'stid'  => self::$stid,
                    'type'  => '销售业绩统计',
                    'value' => json_encode(
                        [
                            "board",
                            "performance_goals",
                            "payment",
                            "contract_money",
                            "kpi_analysis",
                            "losing_analysis",
                            "sign_ranking",
                            "goal_achievement",
                        ],
                        320
                    ),
                ],
            ));
        }
        //判断是否有客户分析设置
        if (static::total(array('table' => 'user_setting', 'where' => "stid = '" . self::$stid . "' and coid='" . self::$coid . "' and type = '客户分析'")
            ) == 0) {
            insert(array(
                'table' => 'user_setting',
                'field' => [
                    'stid'  => self::$stid,
                    'coid'  => self::$coid,
                    'type'  => '客户分析',
                    'value' => json_encode(
                        [
                            "geographical",
                            "industry_scale",
                            "status_funnel",
                            "channel_analysis",
                            "customer_add",
                            "customer_ranking",
                            "conversion_rate",
                        ],
                        320
                    ),
                ],
            ));
        }
    }

    /** 获取仓库查询条件
     *
     * @param string $field
     */
    public static function getWarehouseSql($field = 'id')
    {
        return !empty(self::$warehouse) ? " and $field in ('" . implode("','", self::$warehouse) . "') " : "";
    }

    /**
     * 查找当前使用的coid
     *
     * @return mixed
     */
    public static function findCoid(): mixed
    {
        $company = query('company', "isDel=0");
        if (empty($company['coid'])) {
            //默认账套
            static::insert(array(
                'table' => 'company',
                'field' => [
                    'coid'       => self::getId(),
                    'name'       => '默认账套',
                    'startDate'  => date('Y-m'),
                    'rule'       => 'smallEnterpriseRule',
                    'taxType'    => '小规模纳税人',
                    'isAudit'    => 0,
                    'isDel'      => 0,
                    'stid'       => 'Ore126054470Vd',
                    'codeLength' => companyClass::codeLength
                ],
            ));
        }

        $record = query('user_setting', "stid = '" . self::$stid . "' and type = '当前使用账套'");
        if (empty($record['id'])) {
            $company = query('company', "isDel = 0");
            self::updateCoidRecord($company['coid']);
            return $company['coid'];
        } else {
            $company = query('company', "coid = '$record[value]'");
            if (empty($company['coid'])) {
                $company = query('company', "isDel = 0");
                self::updateCoidRecord($company['coid']);
                return $company['coid'];
            }
        }
        return $record['value'];
    }

    /**
     * 查找公共设置
     *
     * @return mixed
     */
    public static function findOptionSetting(): mixed
    {
        $publicSettings = optionSettingClass::getSetting('公共');
        if (empty($publicSettings)) {
            //公共设置数组
            $setting        = [
                '公共'     => [
                    'lossRate'              => '2',
                    'batchCtrl'             => [
                        'auto'   => '1',
                        'option' => '1',
                        'period' => '1',
                    ],
                    'barcodeCtrl'           => [
                        'merge'  => 0,
                        'option' => 0,
                    ],
                    'invoicePrice'          => 0,
                    'materialCode'          => 0,
                    'materialRate'          => 0,
                    'materialStop'          => 0,
                    'clockAccounting'       => 0,
                    'documentReview'        => [],
                    'numPrecision'          => [
                        'num'         => '2',
                        'numLostZero' => '1',
                    ],
                    'quoteWithTax'          => 0,
                    'companyCanStop'        => '1',
                    'conversionRate'        => 0,
                    'pricePrecision'        => [
                        'num'           => '4',
                        'priceLostZero' => '1',
                    ],
                    'amount'                => [
                        'num'            => '2',
                        'amountLostZero' => '1',
                    ],
                    'showBomCatalog'        => '1',
                    'depreciationrate'      => 0,
                    'companyRepeatCtrl'     => '提示',
                    'materialRepeatDeal'    => [
                        'method' => 'ban',
                        'option' => 0,
                    ],
                    'companyRepeatItemCtrl' => [
                        'companyName',
                        'contactTel',
                    ],
                ],
                '销售'     => [
                    'autoOut'         => 0,
                    'ctrlSale'        => 0,
                    'ctrlUnit'        => 0,
                    'creditCtrl'      => [
                        'way'          => '保存',
                        'option'       => 0,
                        'saleMoney'    => '1',
                        'bookingMoney' => '1',
                    ],
                    'saleStrict'      => 0,
                    'checkRepeat'     => 0,
                    'quoteWithTax'    => 0,
                    'salePriceCtrl'   => [
                        'way'    => '',
                        'method' => '',
                        'option' => 0,
                    ],
                    'saleWithOrder'   => 0,
                    'machiningStrick' => 0,
                    'refundWithOrder' => 0,
                ],
                '采购'     => [
                    'checkRepeat'         => 0,
                    'refundOrder'         => 0,
                    'purchaseAutoIn'      => 0,
                    'purchaseStrict'      => 0,
                    'purchaseMustOrder'   => 0,
                    'purchasePriceCtrl'   => [
                        'way'    => '',
                        'method' => '',
                        'option' => 0,
                    ],
                    'purchaseApplyStrict' => 0,
                    'purchaseBaseWithTax' => 0,
                ],
                '委外'     => [
                    'reverseCheck'           => 0,
                    'bomShowMethod'          => 0,
                    'allowNewMaterial'       => 0,
                    'outsourceTaxPrice'      => 0,
                    'outsourcePriceCtrl'     => [
                        'way'    => '',
                        'method' => '',
                        'option' => 0,
                    ],
                    'outsourceProcessIn'     => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'outsourceStrictPick'    => '1',
                    'outsourceBaseWithTax'   => 0,
                    'outsourceStrictInStock' => '1',
                ],
                '物流'     => [
                    'sourceOrder'  => [
                        'saleSendOrder',
                    ],
                    'autoOutStock' => '1',
                ],
                '库存'     => [
                    'autoBatch'          => [
                        'method' => '现存量',
                        'option' => '1',
                    ],
                    'estimateIn'         => [
                        'purchaseWaitIn',
                        'allocationWaitIn',
                        'machiningWaitIn',
                    ],
                    'estimateOut'        => [
                        'sendWaitIn',
                        'pickWaitOut',
                        'ingOrderWaitOut',
                    ],
                    'zeroOutCtrl'        => '1',
                    'checkCtrl'          => '1',
                    'inStockLimit'       => '0',
                    'outStockLimit'      => '0',
                    'mrpWarehouse'       => [
                        'aa78f3ab09c6c945',
                        'a7d860712d4a8038',
                        'a37e413d8b922156',
                        'aaf4d39671378ad6',
                        'a4448d3a97f30db5',
                        'a53bd5b022c8ca4e',
                        'a5bb1582d845ef82',
                        'a6830d975e7d1083',
                        'a6b0da86d5223347',
                        'a9ad7cbb06387d78',
                        'aae7a8911c82f4e0',
                        'ab6435327d036409',
                    ],
                    'outAllowZero'       => '1',
                    'inventoryCtrl'      => [
                        'val'    => [
                            'saleSendOrder',
                            'inventoryOrder',
                        ],
                        'option' => '1',
                    ],
                    'noCheckManage'      => 0,
                    'warehousePosition'  => [
                        'auto'   => '1',
                        'method' => 'auto',
                        'option' => '1',
                    ],
                    'inventoryStockCtrl' => '1',
                    'inventoryStockWarn' => '1',
                ],
                '核算'     => [
                    'costRate'                   => [
                        'rate'   => '10',
                        'option' => '1',
                    ],
                    'refundPrice'                => '结存成本',
                    'inStockPrice'               => '上次出库成本',
                    'outStockPrice'              => '参考成本',
                    'costValueMethod'            => '手工录入',
                    'machiningInOrderShowDetail' => '1',
                ],
                '生产'     => [
                    'piecePrice'                  => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'reverseCheck'                => 0,
                    'processSecUnit'              => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'autoNewSendOrder'            => '1',
                    'withOutMaterial'             => 0,
                    'withOutBom'                  => 0,
                    'machiningAllowAdd'           => 0,
                    'machiningOrderBom'           => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'beyondPurchasePlan'          => 0,
                    'mobileProcessSplit'          => 0,
                    'allowMoreProcessNum'         => '1',
                    'beyondMachiningPlan'         => 0,
                    'beyondOutsourcePlan'         => 0,
                    'mobileProcessChoose'         => [
                        'method' => 'zero',
                        'option' => 0,
                    ],
                    'processReportByFlow'         => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'productWithOutCheck'         => [
                        'way'    => 'endNum',
                        'method' => '提交',
                        'option' => '1',
                    ],
                    'machiningOrderStrict'        => '1',
                    'machiningOrderStrictIn'      => 0,
                    'mobileProcessDefaultNum'     => [
                        'num'    => 0,
                        'method' => 'zero',
                        'option' => 0,
                    ],
                    'machiningOrderPickStrict'    => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'materialControlAfterSend'    => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'machiningOrderProcessStrict' => [
                        'method' => '',
                        'option' => 0,
                    ],
                    'productCtrlMethod'           => 'productCard',
                ],
                '质量'     => [
                    'checkOrderBad'          => [
                        'val'    => 'checkNum',
                        'option' => '1',
                    ],
                    'checkOrderDefault'      => [
                        'val'    => '单据数量',
                        'option' => '1',
                    ],
                    'productNumControll'     => [
                        'way'    => 'finalProcess',
                        'method' => '提交',
                        'option' => '1',
                    ],
                    'selfMadeOrderCheck'     => [
                        'val'    => [
                        ],
                        'option' => 0,
                    ],
                    'purchaseAutoInStock'    => 0,
                    'maintainQualityOrder'   => [
                        'val'    => [
                        ],
                        'option' => 0,
                    ],
                    'diffPassAndFailedBatch' => [
                        'val'    => '',
                        'option' => 0,
                    ],
                ],
                '往来账/出纳' => [
                    'endToBook'           => '1',
                    'feeNeedApply'        => 0,
                    'outsourceForPay'     => 0,
                    'purchaseNeedPay'     => 0,
                    'cashAndBankAudit'    => '1',
                    'otherPayNeedApply'   => 0,
                    'purchaseOrderForPay' => 0,
                ],
                '总账'     => [
                    'dayBook'          => 0,
                    'deficit'          => 0,
                    'cashFlow'         => 0,
                    'lossRate'         => 2,
                    'assetCode'        => 0,
                    'sameAudit'        => '1',
                    'codeLength'       => [
                        '2',
                        '2',
                        '2',
                    ],
                    'cashierSign'      => '1',
                    'depreciation'     => '1',
                    'invoicePrice'     => '6',
                    'numPrecision'     => [
                        'num'         => '2',
                        'numLostZero' => 0,
                    ],
                    'afterAuditMark'   => 0,
                    'conversionRate'   => 2,
                    'pricePrecision'   => [
                        'num'           => '2',
                        'priceLostZero' => 0,
                    ],
                    'depreciationrate' => '2',
                ],
            ];
            $publicSettings = $setting['公共'];
            foreach ($setting as $key => $val) {
                static::insert(array(
                    'table' => 'option_setting',
                    'field' => [
                        'id'      => self::getId(),
                        'coid'    => self::$coid,
                        'type'    => $key,
                        'setting' => json_encode($val, 320),
                    ],
                ));
            }
        }
        return $publicSettings;
    }

    /**
     * 记录当前使用的账套
     */
    public static function updateCoidRecord($coid): bool
    {
        if (empty($coid)) {
            return false;
        }
        $record = query('user_setting', "stid = '" . self::$stid . "' and type = '当前使用账套'");
        if (empty($record['id'])) {
            $warn = static::insert(array(
                'table' => 'user_setting',
                'field' => [
                    'type'  => '当前使用账套',
                    'value' => $coid,
                    'stid'  => self::$stid,
                ],
            ));
        } else {
            $warn = static::update(array(
                'table' => 'user_setting',
                'field' => [
                    'value' => $coid,
                ],
                'where' => "id = '$record[id]'",
            ));
        }
        if (in_array($warn, ['新增成功', '更新成功'])) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取用户权限
     *
     * @return array
     */
    public static function getUserPower(): array
    {
        $array     = [];
        $roleArray = (array)json_decode(self::$user['role'], true);
        if ($roleArray) {
            foreach ($roleArray as $id) {
                $role = query('role', " id = '$id' ");
                $temp = isset($role['power']) ? (array)json_decode($role['power'], true) : [];
//                $array = array_merge($array, $temp);
                $array = self::mergePower($array, $temp);
            }
        }
        return $array;
    }

    /**
     * 合并权限
     *
     * @param $oldArray
     * @param $newArray
     * @return array
     */
    public static function mergePower($oldArray, $newArray): array
    {
        if (empty($oldArray) || !is_array($oldArray) || count($oldArray) == 0) {
            return $newArray;
        }
        if (empty($newArray) || !is_array($newArray) || count($newArray) == 0) {
            return $oldArray;
        }
        $powerAll = [];
        foreach ($oldArray as $name => $array) {
            if (is_array($array)) {
                foreach ($array as $power) {
                    if (!isset($powerAll[$name])) {
                        $powerAll[$name] = [$power];
                    } elseif (!in_array($power, $powerAll[$name])) {
                        $powerAll[$name][] = $power;
                    }
                }
            }
        }
        foreach ($newArray as $name => $array) {
            if (is_array($array)) {
                foreach ($array as $power) {
                    if (!isset($powerAll[$name])) {
                        $powerAll[$name] = [$power];
                    } elseif (!in_array($power, $powerAll[$name])) {
                        $powerAll[$name][] = $power;
                    }
                }
            }
        }
        $data = [];
        foreach ($powerAll as $name => $array) {
            $temp = [];
            foreach ($array as $val) {
                $temp[] = $val;
            }
            $data[$name] = $temp;
        }
        return $data;
    }

    /**
     * 权限函数
     *
     * @param string $page
     * @param string $power
     * @return bool
     */
    public function power(string $page, string $power): bool
    {
        $myAuthority = isset($this->controlPower[$page]) ? (array)$this->controlPower[$page] : [];
        if ($power == '*') {
            return !empty(count($myAuthority));
        }
        return in_array($power, $myAuthority);
    }

    /**
     * 查看自己
     *
     * @param string $page
     * @param string $field
     * @return string
     */
    public function seeSelf(string $page, string $field = 'stid'): string
    {
        $where = '';
        if (!$this->power($page, 'seeAll')) {
            $where = " and $field = '{$this->control['stid']}' ";
        }
        return $where;
    }

    /*添加日志
    $data = array(
        "type" => "configure.php中的权限类型，如job，client",
        "text" => "日志说明",
        "stid" => "编辑人",//非必填
    );
    */
    public function logText($data)
    {
        $finger = 0;
        //检查权限
        foreach ($this->powerAll as $oneKey => $oneArray) {
            foreach ($oneArray as $twoArray) {
                foreach ($twoArray as $threeArray) {
                    if (array_key_exists($data['type'], $threeArray)) {
                        $finger = 2;
                    }
                }
            }
        }
        $data['coid'] = self::$coid;
        //判断
        if ($finger != 2) {
            test("【" . $data['text'] . "】日志插入失败，原因：未找到权限类型");
        } elseif (empty($data['text'])) {
            test("【" . $data['type'] . "】日志插入失败，原因：日志说明为空");
        } else {
            if (empty($data['stid'])) {
                $data['stid'] = $this->control['stid'];
            }
            $data['time'] = date("Y-m-d H:i:s");
            return insert(["table" => "log", "field" => $data]);
        }
        return false;
    }

    /**
     * 下载桌面快捷方式
     */
    public function desktopShortcut()
    {
        $name = para("name");
        $ico  = root . 'favicon.ico';
        echo <<<efo
<!DOCTYPE html>
<html>
    <head>
        <title>{$name}</title>  
        <link rel="icon" href="{$ico}" type="image/x-icon"> 
    </head>
    <body>
        <script type="text/javascript">window.location.href="{$this->root}";</script>
    </body>
</html>
efo;

    }

    /**
     * 登录
     */
    public function login()
    {
        //生成表单
        $tr    = [
            "<i class='user-login'></i>" => text(
                ["name" => "userName", "title" => L('adIndex.login.userName'), 'blur' => 'validate', "other" => 'required pattern="\S+.*" ']
            ),
            "<i class='pwd-login'></i>"  => password(
                ["name" => "password", "title" => L('adIndex.login.password'), 'blur' => 'validate', "other" => 'required pattern="\S+.*" ']
            ),
            "<i class='auth-login'></i>" => text(["name" => "prove", "class" => 'prove', "title" => L('adIndex.login.prove'), 'blur' => 'validate', "other" => 'required pattern="\S+.*" ',]) . "<img src='" . root . "library/libData.html?type=proveImg' id='checkNumImg' class='checkNumImg' title='" . L('adIndex.login.checkNumImg') . "'>",
        ];
        $table = "<table>\n";
        foreach ($tr as $key => $value) {
            $table .= "<tr>\n<td>" . $key . "</td>\n<td>" . $value . "</td>\n</tr>";
        }
        $table .= "\n</table>";
        //生成页面

        $html = "
		 <script src='https://wwcdn.weixin.qq.com/node/wework/wwopen/js/wwLogin-1.2.5.js' type='text/javascript'></script>
		 <img class='loginBack' src='" . img("adLoginBackImg") . "'>
       </div>
		<div class='loginWin'>
            <div class='login-header'>
                <div class='login-qr-img-msk'></div>
                <div class='login-qr-img' id='loginSwitch' current='account'>
                    <img src='" . root . "img/websiteImg/qr_login.png'>
                </div>
            </div>
            <div class='login-main'>
                <img class='loginIco' src='" . img('adloginIcoImg') . "'>
                <h2>" . para("name") . "</h2>
                <div id='login-main-account'>
                    <form name='loginForm'>
                        " . $table . hidden(['name' => 'did', 'id' => 'did']) . "
                    </form>
                </div>
                <div id='login-main-qr' class='hide'>
                </div>
            </div>
            <div class='login-bottom'>
                <p>
                    <button subButton='yes' type='button' class='subButton'  id='login-submit' onClick=\"subForm('loginForm',root+'library/libData.html?type=adLogin')\">" . L('adIndex.login.subButton') . "</button>
                </p>
                <p>
                    <span class='cursor right forgot-password'>
                        <a href='" . root . "control/adIndex.html?cla=desktopShortcut' download='" . para("name") . ".html'>保存到桌面</a>
                    </span>
                </p>
                <p>" . str_replace('.=', 'style=', self::htmlDecode(para('IcpInfoText'))) . "</p>
            </div>
		</div>";
        $js   = "
        <script src=\"../static/javascript/fingerprint2.min.js\" onerror=\"console.error('Failed to load fingerprint2.min.js')\"></script>
        <script>
        $(function(){
            const did = document.getElementsByName('did');
            const logFingerprint = function(components) {
                const values = components.map(function(component) {
                    return component.value;
                });
                const murmur = Fingerprint2.x64hash128(values.join(''), 31);
                console.log('Fingerprint computed:', murmur);
                did[0].value = murmur;
            };
            // 检查 fingerprint2.min.js 是否加载成功
            if (typeof Fingerprint2 === 'undefined') {
                alert('检测到广告拦截插件，可能会影响网站的正常功能。请停用广告拦截插件或将此网站加入白名单。');
            } else {
                if (window.requestIdleCallback) {
                    requestIdleCallback(function() {
                        Fingerprint2.get(logFingerprint);
                    });
                } else {
                    setTimeout(function() {
                        Fingerprint2.get(logFingerprint);
                    }, 500);
                }
            }
            // 登录函数
            login();
        })
        </script>";
        return head("ad") . $html . $js . warn() . "\n</body>\n</html>";
    }

    /**
     * 设置当前消息为已读状态
     *
     * @return void
     */
    public function messageRead()
    {
        $messageId   = [];
        $messageId[] = $this->get('messageRead');
        $messageId[] = $this->post('messageRead');
        foreach ($messageId as $id) {
            $message = query("message", " id = '$id' ");
            if ($message['id'] && $message['stid'] == $this->control['stid']) {
                update(array(
                    "table" => "message",
                    "field" => array(
                        "see"     => "是",
                        "seeTime" => date("Y-m-d H:i:s"),

                    ),
                    "where" => " id = '$id' ",
                ));
            }
        }
    }


    /**
     * 审批流程输出函数
     *
     * @param array $data
     *     $data = array(
     *     "target" => "审批对象",
     *     "type" => "返回类型：审批流，初始化",
     *     );
     * @return void
     */
    public function examine(array $data)
    {
        //数据准备
        $examine = query("examine", "target = '" . $data['target'] . "' and jobId = '" . $this->control['jobId'] . "'");
        //拼接审批流
        if (empty($data['target'])) {
            $para['warn'] = "审批对象为空";
        } elseif (empty($examine['id'])) {
            $para['warn'] = "未找到【" . $data['target'] . "】的审批流程，请通知行政设置！";
        } elseif (empty($data['type'])) {
            $para['warn'] = "审批流程返回类型为空";
        } elseif ($data['type'] == "审批流") {
            $stidArray = json_decode($examine['stid'], true);
            $nameArray = [];
            foreach ($stidArray as $stid) {
                $staff       = query("staff", "stid = '" . $stid . "'");
                $nameArray[] = $staff['name'];
            }
            $para = implode(" -> ", $nameArray);
        } elseif ($data['type'] == "初始化") {
            $stidArray    = json_decode($examine['stid'], true);
            $examineArray = [];
            foreach ($stidArray as $stid) {
                $examineArray[$stid] = "审核中";
            }
            $para['one']  = $stidArray[0];//第一个审批人ID
            $para['stid'] = json_encode($examineArray, 320);
        } else {
            $para['warn'] = "未知审批流程返回类型";
        }
        //非空处理
        if ($data['type'] == "审批流" and !empty($para['warn'])) {
            $para = $para['warn'];
        }
        //返回
        return $para;
    }

    /*展示型table拼接-按钮，不同类型的按钮对应不同的参数
    $data = array(
        array(
            "name" => "按钮名称",
            "type" => "弹出层",//按钮类型
            "cla" => "需要调用的类名称",
            "fun" => "需要调用的函数名称",
            "post" => "向调用的函数传递的POST参数",
            'style' => '附加类'
        ),
        array(
            "name" => "按钮名称",
            "type" => "文件下载",
            "fileName" => "文件名称",
            "url" => "文件路径",
        ),
        array(
            "name" => "按钮名称",
            "type" => "顶部页卡",
            "title" => "顶部页卡标题",
            "url" => "顶部页卡路径",
        ),
        array(
            "name" => "按钮名称",
            "type" => "外部链接",
            "url" => "路径",
        ),
        array(
            "name" => "按钮名称",
            "type" => "点击事件",
            "fun" => "js函数",
        ),
    );
    */
    public function tableShowButton($data)
    {
        //初始化
        $li      = $html = "";
        $liClass = [
            "弹出层"  => "alert",
            "文件下载" => "download",
            "顶部页卡" => "toppage",
            "外部链接" => "href",
            "点击事件" => "click",
        ];
        //遍历
        foreach ($data as $array) {
            $style = isset($array['type']) ? ("li-btn-" . $liClass[$array['type']] . (isset($array['style']) && $array['style'] ? ' ' . $array['style'] . ' ' : '')) : '';
            switch ($array['type']) {
                case '弹出层':
                    if (isset($array['post'])) {
                        if (is_array($array['post'])) {
                            $post = [];
                            foreach ($array['post'] as $k => $v) {
                                $post[] = "'" . $k . "':'" . $v . "'";
                            }
                            $json = "{" . implode(",", $post) . "}";
                        } else {
                            $json = $array['post']; //自定义json字符串，用于serialize表单序列化，以及自定义拼接参数
                        }
                    }
                    $li .= "<span class='spanButton $style' onclick=\"layer('" . $array['cla'] . "','" . $array['fun'] . "'," . $json . ")\">" . $array['name'] . "</span>";
                    break;
                case '文件下载':
                    $li .= "<span class='spanButton $style'><a href='" . $array['url'] . "' download='" . $array['fileName'] . "' target='_blank'>" . $array['name'] . "</a></span>";
                    break;
                case '顶部页卡':
                    $li .= "<span class='spanButton $style' onclick=\"newIframe('" . $array['title'] . "','" . $array['url'] . "')\">" . $array['name'] . "</span>";
                    break;
                case '外部链接':
                    $li .= "<a class='spanButton $style' href='" . $array['url'] . "' target='_blank'>" . $array['name'] . "</a>";
                    break;
                case '点击事件':
                    $li .= "<span class='spanButton $style' onclick=\"" . $array['fun'] . "\" title='" . (isset($array['title']) ? $array['title'] : $array['name']) . "'>" . $array['name'] . "</span>";
                    break;
                default:
                    $li .= "no";
                    break;
            }
        }
        //按钮拼接
        if (isset($li) && $li) {
            $html = $li . clear;
        }
        //返回
        return $html;
    }

    /*展示型table拼接*/
    public function tableShow($data, $sign = 0)
    {
        //初始化
        $html = "";
        $max  = 0;
        //获取表格最大列数
        foreach ($data as $oneKey => $ulArray) {
            if ($oneKey !== "button") {
                foreach ($ulArray as $twoKey => $liArray) {
                    $num = count($liArray);
                    if ($num > $max and $twoKey !== "button") {
                        $max = $num;
                    }
                }
            }
        }
        //数据分析
        foreach ($data as $oneKey => $ulArray) {
            if ($oneKey === "button") {
                $html .= "<div class='tab-button'>" . $this->tableShowButton($ulArray) . "</div>";
            } else {
                //拼接表格
                $button = $ul = "";
                foreach ($ulArray as $twoKey => $liArray) {
                    if ($twoKey === "button") {
                        $button = $this->tableShowButton($liArray);
                    } else {
                        //初始化参数
                        $n     = 0;
                        $liNum = count($liArray);
                        $li    = "";
                        //遍历数组
                        foreach ((array)$liArray as $key => $value) {
                            //计数
                            $n++;
                            //内容
                            $value = kong($value);
                            if (is_int($key)) {
                                $content = $value;
                            } else {
                                if ($sign == 1) {
                                    $content = "<div class='search-line'>
                                                <div class='search-line-title title-color' title='" . $key . "'>" . $key . "：</div>
                                                <div>" . $value . "</div>
                                            </div>";
                                } else {
                                    $title       = strip_tags($key) !== $key ? '' : $key;
                                    $field_title = strip_tags($value) !== $value ? '' : $value;
                                    $content     = "<div class='detail-line-title' title='" . $title . "'>" . $key . "：</div>
                                                <div class='detail-line-field' title='" . $field_title . "'>" . $value . "</div>
                                            ";
                                }
                            }
                            //如果单元格不足，则补全
                            if ($liNum < $max and $liNum == $n) {
                                $m     = $max - $liNum + 1;
                                $style = " style='flex:" . $m . "' ";
                            } else {
                                $style = "";
                            }
                            //拼接本单元格
                            $li .= "<li " . $style . ">" . $content . "</li>";
                        }
                        //拼接本行
                        $ul .= "<ul class='show'>" . $li . "</ul>";
                    }
                }
                //没有键名的数组，置为空
                if (is_int($oneKey)) {
                    $oneKey = '';
                }
                if ($oneKey) {
                    $oneKey = "<div class='small-title'>" . $oneKey . "</div>";
                }
                if (count($ulArray) > 0) { //数组中有值才显示
                    //拼接本表格
                    $html .= "
                            <div class='tableShow'>
                                " . $oneKey . $button . $ul . "
                            </div>
                            ";
                }
            }
        }
        //返回
        return $html;
    }

    /**
     * Desc : 详情页列表
     * User : you name
     * Date : 2024-03-21 11:31
     * @param $data
     */
    public function detailList($data)
    {
        $attribute = "";
        $class     = isset($data['class']) ? $data['class'] : '';
        $attribute .= " class='detail-single " . $class . "' ";
        if (isset($data['id'])) {
            $attribute .= " id='" . $data['id'] . "' ";
        }
        if (isset($data['other'])) {
            $attribute .= " " . $data['other'];
        }
        $title = '';
        if (isset($data['title'])) {
            if (isset($data['button'])) {
                $title .= "<div class='detail-table-toolbar'><span class='detail-table-title'>{$data['title']}</span>{$data['button']}</div>";
            } else {
                $title .= "<p>{$data['title']}</p>";
            }
        }
        $html = isset($data['html']) && $data['html'] ? $data['html'] : '无';
        return "
                <div " . $attribute . ">
                    " . $title .
            $html . "
                </div>
                ";
    }

    /*详情页页单块独立
    $data = array(
        "title" => 'html'...
    );
    */
    public function detailBlock($data)
    {
        //初始化
        $html = "";
        //数据分析
        foreach ($data as $oneKey => $oneValue) {
            //没有键名的数组，置为空
            if (!is_int($oneKey) && $oneKey) {
                $oneKey = "<p>" . $oneKey . "</p>";
            }
            if ($oneValue) { //数组中有值才显示
                //拼接本表格
                $html .= "
                        <div class='detailBlock'>
                            " . $oneKey . $oneValue . "
                        </div>
                        ";
            }
        }
        //生成页面
        return $html;
    }

    /*文件创建与编辑函数
    $data = array(
        "url" => "文件路径",
        "text" => "文件内容",
    );
    */
    public function fileEdit($data)
    {
        if (file_exists($data['url'])) {
            file_put_contents($data['url'], $data['text']);
        } else {
            $array = explode("/", $data['url']);
            $url   = "";
            foreach ($array as $name) {
                if (!empty($name)) {
                    $url .= "/" . $name;
                    if (!file_exists($url)) {//如果此路径不存在
                        if ($url == $data['url'] and strstr($name, ".")) {//如果已经拼接到完整路径，且检查到最末端带文件名后缀，则说明需要创建文件，而非文件夹
                            $file = fopen($url, "w");                     //创建文件
                            fwrite($file, $data['text']);                 //写入文件内容
                        } else {
                            mkdir($url);//则创建文件目录
                        }
                    }
                }
            }
        }
    }

    /*列表页控件
    $data = array(
        //列表多选框
        "box" => array(
            "name" => "多选框名称",
            "value" => "多选框值",
        ),
        //按钮
        "见$para变量" => array(
            "title" => "标题",
            "click" => "点击事件",
        ),
        //文件下载
        "download" => array(
            "type" => "文件类型，如doc,xls",
            "name" => "文件名称",
            "href" => "文件跟目录路径",
        ),
        //文件预览
        "preview" => array(
            "format" => "文件格式，如doc,xls",
            "name" => "文件名称",
            "href" => "文件跟目录路径",
        ),
        //图片预览
        "img" => array(
            "title" => "标题",
            "href" => "根目录路径",
        ),
    );
    */
    public function dominate($data)
    {
        //参数准备
        $html = "";
        $para = array(
            "detail"       => "详情",
            "edit"         => "编辑",
            "auditing"     => "审核",
            "rebut"        => "驳回",
            "upload"       => "上传",
            "share"        => "分享",
            "affair"       => "事务",
            "agent"        => "代理",
            "client"       => "客户",
            "order"        => "订单",
            "project"      => "项目",
            "allot"        => "任务",
            "invoice"      => "发票填开",
            "use"          => "资产领用",
            "useRecord"    => "领用记录",
            "cut"          => "资产核减",
            "cutRecord"    => "核减记录",
            "revert"       => "资产归还",
            "revertRecord" => "归还记录",
            "copy"         => "复制",
            "code"         => "代码",
            "signYellow"   => "已标记",
            "signGray"     => "未标记",
            "download"     => "下载",
            "preview"      => "文档预览",
            "img"          => "图片预览",
            'browse'       => '预览',
            "follow"       => "跟进记录",
            "obtain"       => '获取',
            'print'        => '打印',
            'scrap'        => '报废',
            'rework'       => '返工',
            'receive'      => '接收',
            'refund'       => '退货',
            'backCar'      => '还车',
            'add'          => '增加',
            'report'       => '报工',
            'track'        => '单据追踪',
            'setting'      => '设置',
            'add_one'      => '增加',
        );
        //循环
        foreach ($data as $name => $array) {
            //标题
            $title = (empty($array['title'])) ? ($para[$name] ?? null) : $array['title'];

            if (empty($array)) {
                continue;
            }
            $other = isset($array['other']) && $array['other'] ? $array['other'] : '';
            //生成HTML
            if ($name == "box") {
                $html .= "\n<label class='listCheckbox'><input name='" . $array['name'] . "[]' type='checkbox' value='" . $array['value'] . "' " . $other . "/><span title='".$title."'></span></label>";
            } elseif ($name == "download") {
                if (!empty($array['href'])) {
                    $html .= "\n<a target='_blank' href='" . root . $array['href'] . "' download='" . $array['name'] . "' title='" . $title . "'><img src='" . root . "img/control/download.svg' class='listIco' " . $other . "></a>";
                }
            } elseif ($name == "preview") {
                if (!empty($array['href'])) {
                    $url  = fileUploadClass::wpsView($array);
                    $html .= "\n<a target='_blank' href='" . $url . "' title='" . $title . "'><img src='" . root . "img/control/preview.svg' class='listIco' " . $other . "></a>";
                }
            } elseif ($name == "img") {
                if (!empty($array['href'])) {
                    $html .= "\n<a target='_blank' href='" . root . $array['href'] . "?time=" . time() . "'><img src='" . root . "img/control/img.svg' title='" . $title . "' class='listIco' " . $other . "></a>";
                }
            } elseif (array_key_exists($name, $para)) {
                $html .= "\n<img onclick=\"" . $array['click'] . "\" title='" . $title . "' src='" . root . "img/control/" . $name . ".svg' class='listIco' " . $other . ">";
            }
        }
        //返回
        return $html;
    }

    /*wps文件预览
    $data = array(
        "format" => "文件格式，如doc,xls",
        "name" => "文件名称",
        "href" => "文件跟目录路径",
    );
    */
    public static function wps($data)
    {
        return fileUploadClass::wpsView($data);
    }


    /**
     * 曲线图模板
     *
     * @param array $data = ["name" => "纵坐标标题一维数组", "series" => [ ["name" => "系列名称","data" => ["数据"] ],… ] ];
     * @param string $type 类型：折线 line ,柱状图 bar
     */
    public function curve(array $data, string $type = 'line')
    {
        $areaStyle = '';
        if ($type == 'area') {
            //面积曲线
            $type      = 'line';
            $areaStyle = "areaStyle:{},";
        }
        //系列
        $series = $legend = "";
        // 自定义
        $keys   = ['stack', 'emphasis', 'smooth', 'barMaxWidth', 'itemStyle', 'smooth'];
        $result = isset($data['series'][0]) ? array_intersect($keys, array_keys($data['series'][0])) : [];
        foreach ($data['series'] as $array) {
            $comma     = empty($series) ? '' : ',';
            $attribute = '';
            foreach ($result as $key) {
                if (isset($array[$key])) {
                    $attribute .= $key . ':' . (($key == 'emphasis' || $key == 'itemStyle') ? $array[$key] : "'$array[$key]'") . ',';
                }
            }
            $list_type = $array['type'] ?? $type;
            $series    .= $comma . "
			{
				name: '" . $array['name'] . "',
				type: '$list_type',
                $attribute
				data: [" . implode(",", $array['data']) . "],
				$areaStyle
			}";
            $legend    .= "'{$array['name']}',";
        }
        $legend      = rtrim($legend, ',');
        $text        = $data['text'] ?? '';
        $subtext     = $data['subtext'] ?? '';
        $legendStyle = $data['legendStyle'] ?? '';
        $graphic     = $data['graphic'] ?? '';
        //生成html
        $option = "
		var option = {
		    // ... 其他配置项  
            graphic: {  
                type: 'text',  
                left: 'right',  // 文字在右上角  
                top: '5',  
                style: {  
                    text: '{$graphic}',  // 文字内容  
                    textAlign: 'center',  // 文字水平对齐方式  
                    fill: '#000',  // 文字颜色  
                    fontSize: 12  // 文字大小  
                }  
            },
			title: {
                text: '{$text}',
                subtext: '{$subtext}',
                left: 'right',
                top: '0%'
            },
			tooltip: {
                trigger: 'axis'
            },
			legend: {
                top:'bottom',
				data: [" . $legend . "],
				$legendStyle
			},
			grid: {
                left: '3%', right: '3%', bottom: '10%', containLabel: true
			},
			toolbox: {
				feature: {saveAsImage: {show: false,} }
			},
			xAxis: {
				type: 'category', boundaryGap: false, data: ['" . implode("','", $data['name']) . "']
			},
			yAxis: {
				type: 'value', axisLabel:{ margin: 45, }, //刻度标签与轴线之间的距离
			},
			series: [
				" . $series . "
			]
		};";
        return $this->echarts($option);
    }

    /**
     * 柱状图
     *
     * @param array $data = ["name" => "纵坐标标题一维数组", "series" => [ ["name" => "系列名称","data" => ["数据"] ],… ] ];
     * @return string
     */
    public function barCharts(array $data)
    {
        //系列
        $series = "";
        $legend = '';
        foreach ($data['series'] as $array) {
            if (empty($series)) {
                $comma = "";
            } else {
                $comma = ",";
            }
            $series .= $comma . "
			{
			    name:'{$array['name']}',
				type: 'bar',
				data: [" . implode(",", $array['data']) . "],
			}";
            $legend .= $array['name'] . "','";
        }
        $text    = $data['text'] ?? '';
        $subtext = $data['subtext'] ?? '';
        //生成html
        $option = "
		var option = {
		    title: {
                text: '$text',
                subtext: '$subtext',
                left: 'right',
                top: '0%'
            },
            tooltip:{
             show:true,
            },
            legend: {
                top:'bottom',
				data: ['" . $legend . "']
			},
			xAxis: {
				type: 'category',
				data: ['" . implode("','", $data['name']) . "']
			},
			yAxis: {
				type: 'value',
			},
			series: [
				" . $series . "
			]
		};";
        return $this->echarts($option);
    }


    /**
     * 销售漏斗
     *
     * @param array $data 如上
     */
    public function funnel(array $data)
    {
        $seriesData = '';
        foreach ($data['series'] as $array) {
            $value      = (is_array($array['data']) ? $array['data'][0] : $array['data']);
            $seriesData .= "{value: $value, name: '{$array['name']}'},";
        }
        $data['sort'] = $data['sort'] ?? 'descending';
        //生成html
        $option = "
        option = {
            tooltip: {
                trigger: 'item',
                formatter: '{b} :    {c}，    {d}%'
            },
            series: [
                {
                    name: ' ',
                    type: 'funnel',
                    label:{
                        position: 'right',
                        formatter: '{a} {b} {c}',
                        color:'#333',
                    },
                    labelLine: {
                        show: true
                    },
                    width: '50%',
                    height: '80%',
                    left: '20%',
                    top: '10%',
                    sort:'{$data['sort']}',
                    data: [
                        $seriesData
                    ]
                }
            ]
        };";
        return $this->echarts($option);
    }



    /*
    *
    * 饼图模板
    * $data = array(
        "title" => "标题",
        "para" => array(
            "value" => "数值",
            "name" => "名称",
        ),
        ...
    );
    */
    /**
     * 饼图模板
     *
     * @param array $data 格式如上
     */
    public function pie(array $data)
    {
        $series = $legend = '';
        foreach ($data['series'] as $array) {
            $legend .= "'{$array['name']}',";
            $value  = (is_array($array['data']) ? $array['data'][0] : $array['data']);
            $series .= '{value:"' . $value . '", name: "' . $array['name'] . '"},';
        }
        $option = <<<EOT
        var option = {
            tooltip: {
                trigger: 'item'
            },
            legend: {
                orient: 'vertical',
                left: 'right',
                top: '0',
                data: [$legend]
            },
            series: [
                {
                    name: ' ',
                    type: 'pie',
                    radius: ['35%', '60%'],
                    labelLine: {
                        length: '5%',
                    },
                    itemStyle: {
                        borderColor: '#fff',
                        borderWidth: 2
                    },
                    label: {
                        formatter: '{c}',
                        // formatter: '{b}：{c}',
                    },
                    data: [$series]
                }
            ]
        };
EOT;
        //返回
        return $this->echarts($option);
    }

    /**
     * 水波球
     */
    public function liquidfill(array $data)
    {
        $series = '';
        foreach ($data['series'] as $array) {
            $value  = (is_array($array['data']) ? $array['data'][0] : $array['data']);
            $series .= '{value:"' . $value . '", name: "' . ($array['name'] ?? null) . '"},';
        }
        $option = <<<EOT
        var option = {
            series: [{
                type: 'liquidFill',
                outline : {
                    show : false
                },
                tooltip : {
                    show : true
                },
                label:{
                    fontSize: 20,
                    color: '#333'
                    // position: 'left',
                },
                color: ['#809dfb'],
                data: [$series]
            }]
        }
EOT;
        $ext    = '<script src="' . $this->root . 'static/javascript/echarts-liquidfill.min.js"></script>';
        //返回
        return $this->echarts($option, $ext);
    }

    /**
     * 甘特图 类似项目进度
     *
     * @param array $data
     *         $data = [
     *         'series' => [
     *         [
     *         'name' => "任务名称",
     *         'data' => ['开始时间', '结束时间’]
     *         ],[],[],
     *         ]
     *         ]
     */
    public function gantt(array $data)
    {
        //系列
        $series = $legend = "";
        foreach ($data['series'] as $key => $array) {
            $key    += 1;
            $legend .= $array['name'] . "','";
            // 构造数据结构
            $series .= <<<EOT
            {
                name: "{$array['name']}",
                type: "bar",
                stack: "总量$key",
                label: {
                    normal: {
                        show: true,
                        color: "#000",
                        position: "left",
                        formatter: function(params) {
                            return params.seriesName
                        }
                    }
                },
                itemStyle: {normal: {borderColor: "#fff", borderWidth: 2}},
                zlevel: -1,
                data: [new Date("{$array['data'][1]}")]
            },
            {
                name: "{$array['name']}",
                type: "bar",
                stack: "总量$key",
                itemStyle: {normal: {color: "white"}},
                zlevel: -1,
                z: 3,
                data: [new Date("{$array['data'][0]}")]
            },
EOT;
        }
        //生成html
        $option = "
	var option = {
			legend: {
                top: 5,
				data: ['" . $legend . "']
			},
			grid: {
                containLabel: true,
                show: false,
                left: 50,
                bottom: 40,
                top: 50
			},
			xAxis: {
                type: 'time',
                position: 'top',
            },
			yAxis: {
				data: [' '],
			},
            dataZoom: [{
                type: 'inside',
            }],
			series: [
				" . $series . "
			]
		};";
        return $this->echarts($option);
    }

    /**
     * 柱形对比
     *
     * @param array $data
     * @return string
     */
    public function contrast(array $data)
    {
        $series = $legend = "";
        foreach ($data['series'] as $array) {
            $legend .= "'{$array['name']}',";
            $value  = (is_array($array['data']) ? $array['data'][0] : $array['data']);
            $series .= <<<EOT
            {
                name: '{$array['name']}',
                type: 'bar',
                barWidth : 25, //宽度
                label: {
                    show: true,
                    position: 'right',
                    formatter: function (params) {
                        return params.value.toFixed(2)+'%'
                    }
                },
                data: [$value]
            },
EOT;
        }

        $option = <<<EOT
        var option = {
            legend: {
                data: [$legend],
                top:'top',
            },
            grid: {
                top:0,
                left: '3%',
                right: '4%',
                bottom: '3%',
                width: '90%',
                containLabel: true
            },
            xAxis: {
                show:false,
            },
            yAxis: {
                show:false,
                data: [ ]
            },
            series: [$series]
        };
EOT;
        return $this->echarts($option);
    }

    /**
     * echarts模板
     *
     * @param string $option
     * @param string $ext 扩展js
     * @return string
     */
    public function echarts(string $option, $ext = null): string
    {
        $id = suiji();
        return "
		<div id='" . $id . "' style='width:100%;height:100%;'></div>
        $ext
		<script type='text/javascript'>
			//基于准备好的dom，初始化echarts实例
			//let myChart = echarts.init(document.getElementById('" . $id . "'),'walden');
			//指定图表的配置项和数据
			" . $option . "
			//使用刚指定的配置项和数据显示图表。
			echarts.init(document.getElementById('" . $id . "'),'walden').setOption(option);
		</script>
		";
    }

    /*获取中间月份
    $data = array(
        "start" => "开始月份",
        "end" => "结束月份",
    );
    */
    public function moon($data)
    {
        $data['end'] = date("Y-m", strtotime($data['end'] . "-20 00:00:00") + 20 * 60 * 60 * 24);//截止时间推算到结束月的下个月
        $startYear   = substr($data['start'], 0, 4);
        $startMoon   = substr($data['start'], 5, 2);
        $endYear     = substr($data['end'], 0, 4);
        $endMoon     = substr($data['end'], 5, 2);
        $moon        = [];
        for ($i = $startYear; $i <= $endYear; $i++) {
            if ($i == $startYear and $i < $endYear) {
                $n1 = $startMoon;
                $n2 = 12;
            } elseif ($i > $startYear and $i < $endYear) {
                $n1 = 1;
                $n2 = 12;
            } elseif ($i == $startYear and $i == $endYear) {
                $n1 = $startMoon;
                $n2 = $endMoon;
            } elseif ($i > $startYear and $i == $endYear) {
                $n1 = 1;
                $n2 = $endMoon;
            } else {
                $n1 = $n2 = 0;
            }
            if ($n1 > 0 and $n2 > 0) {
                for ($n = $n1; $n <= $n2; $n++) {
                    $endTime = $i . "-" . sprintf("%02u", $n);//本次循环的开始时间
                    if (!empty($startTime)) {//计算上一个月的统计数据
                        $moon[] = array("start" => $startTime, "end" => $endTime);
                    }
                    $startTime = $endTime;//上一个循环的开始时间
                }
            }
        }
        return $moon;
    }

    /*审批记录
    $typeId:审批对象ID号
    */
    public function auditingFollow($typeId)
    {
        $sql = find(array("table" => "auditing_follow", "where" => " typeId = '" . $typeId . "' order by time desc"));
        if ($sql['num'] == 0) {
            $html = "<div class='record'>无审批记录</div>";
        } else {
            $html = "";
            foreach ($sql['array'] as $array) {
                $text = preg_replace(array("/\n/"), array("<br>"), $array['text']);
                $html .= "<div class='record'>" . $text . "\n<span class='gray'>" . $array['time'] . "</div>";
            }
        }
        return $html;
    }

    /*带密码的批量删除提示层*/
    public function pasWarn()
    {
        //提示信息
        $paraId = $this->post('cla') . ucwords($this->post('fun'));
        //提交按钮
        $url    = root . "control/adIndex.html?cla=" . $this->post('cla') . "&fun=" . $this->post('fun');
        $button = "<input onclick=\"subForm('pasWarnForm," . $this->post(
                'formName'
            ) . "','" . $url . "')\" type='button' class='button' value='确认提交'>";
        //表单
        $html = $this->layerEdit(array(
            "table" => array(
                array(
                    "提示信息：" => para($paraId),
                ),
                array(
                    must . "登录密码：" => password(array("name" => "password")),
                ),
            ),

        ));
        //返回
        return $this->layer(array("title" => "温馨提示", "button" => $button, "height" => 240, "width" => 600, "zindex" => 98, "html" => $html));
    }

    /*图片显示与编辑
    *$data = array(
        array(
            "title" => "标题",
            "url" => "图像服务器相对路径",
            "cla" => "提交后处理的类名称",
            "fun" => "提交后处理的函数名称",
            "id" => "需要添加或更新图片的记录的主键",
        ),
        ...
    )
    */
    public function photo($data)
    {
        $li = "";
        foreach ($data as $num => $array) {
            //编辑表单
            if (in_array("", [getVal($array, 'fun'), getVal($array, 'cla'), getVal($array, 'id')])) {
                $click = $form = "";
            } else {
                $click = "<img src='" . root . "img/images/clickEdit.png' onclick='document." . $array['fun'] . "Form.file.click();' class='clickIco'>";
                $form  = "
				<form name='" . $array['fun'] . "Form' action='" . root . "control/adIndex.html?cla=" . $array['cla'] . "&fun=" . $array['fun'] . "' method='post' enctype='multipart/form-data' class='hide'>
					<input name='file' type='file' onchange='document." . $array['fun'] . "Form.submit();'>
					<input name='id' type='hidden' value='" . $array['id'] . "'>
				</form>
				";
            }
            //点击显示大图功能
            if (empty($array['url'])) {
                $img = "<img class='smallImg imgHover' src='" . root . "img/images/emptyImg.jpg'>";
            } else {
                if (str_contains($array['url'], "http")) {
                    $r = "";
                } else {
                    $r = root;
                }
                $img = "<a target='_blank' href='" . $r . $array['url'] . "' title='点击查看大图'><img class='smallImg imgHover' src='" . $r . $array['url'] . "'></a>";
            }
            //打印本图像框
            $li .= "
			<li>
				" . $click . "
				<p>" . $array['title'] . "</p>
				<div>" . $img . "</div>
				" . $form . "
			</li>
			";
        }
        return "
		<div class='imgSingle'>
			<ul>" . $li . "</ul>
			<div class='clear'></div>
		</div>
		";
    }

    /*查询某员工的权限
    $data = array(
        "stid" => "需要查询权限的员工ID",
        "page" => "页面名称",
        "power" => "权限代码",
    );
    */
    public function staffPower($data)
    {
        $staff = query("staff", " stid = '$data[stid]' ");
        $job   = query("job", " id = '$staff[jobId]' ");
        $role  = query("role", " id = '$job[roleId]' ");
        $power = json_decode($role['power'], true);
        if (in_array($data['power'], (array)$power[$data['page']])) {
            return true;
        } else {
            return false;
        }
    }

    /*代理商详情页权限*/
    public function agentPower($agid)
    {
        //数据库查询
        $agent = query("agent", "agid = '$agid'");
        //判断
        if (empty($agid)) {
            $json['warn'] = "代理商ID号为空";
        } elseif (empty($agent['agid'])) {
            $json['warn'] = "未找到此代理商";
        } elseif ($agent['stid'] == $this->control['stid'] and !$this->power("agent", "see")) {
            $json['warn'] = "你没有查看代理商的权限";
        } elseif ($agent['stid'] != $this->control['stid'] and !$this->power("agent", "seeAll")) {
            $json['warn'] = "你没有查看全部代理商的权限";
        } else {
            $json = $agent;
        }
        //返回
        return $json;
    }

    /*数据库排序
    $data = array(
        "search" => "查询关键词",
        "default" => "默认排序关键词",
        "array" => array(//排序字典
            "排序字段名称" => array(
                "asc" => "本字段升序排序关键词",
                "desc" => "本字段降序排序关键词",
                "site" => "本字段在表格中列的位置",
            ),
        ),
    );
    */
    public function orderBy($data)
    {
        //有查询条件
        if (!empty($data['search'])) {
            $para = $this->orderByEach(array("search" => $data['search'], "array" => $data['array']));
        }
        //如未找到，则查询默认
        if (empty($para['orderBy'])) {
            $para = $this->orderByEach(array("search" => $data['default'], "array" => $data['array']));
        }
        //返回
        return $para;
    }

    /*数据库排序-循环数组
    $data = array(
        "search" => "查询关键词",
        "array" => "排序字典",
    );
    */
    public function orderByEach($data)
    {
        //参数准备
        $para = array(
            "field"   => "",//sql查询自定义字段
            "orderBy" => "",//sql查询排序代码
            "site"    => "",//排序标记列的位置
            "style"   => "",//排序标记样式
        );
        //遍历排序字典
        foreach ($data['array'] as $name => $array) {
            foreach ($array as $key => $value) {
                if ($data['search'] == $value) {
                    $para['orderBy'] = $name . " " . $key;
                    $para['field']   = $array['field'] ?? null;
                    $para['site']    = $array['site'] ?? null;
                    //排序标签
                    if ($key == "desc") {
                        $para['style'] = orderByDescStyle;
                    } elseif ($key == "asc") {
                        $para['style'] = orderByAscStyle;
                    }
                }
            }
        }
        //返回
        return $para;
    }

    /*数据库排序-循环数组
    $data = array(
        "search" => "查询字段",
        "sort" => "排序方式",
        "array" => "字段别名定义",
    );
    */
    public function listSort($data)
    {
        //参数准备
        $para            = array(
            "field"   => $data['search'],//sql查询自定义字段
            "orderBy" => "",//sql查询排序代码
            "site"    => $data['search'],//排序标记列的位置
            "sort"    => $data['sort'],//排序标记样式
        );
        $name            = isset($data['array'][$data['search']]) ? $data['array'][$data['search']] : $data['search'];
        $para['orderBy'] = $name . " " . $data['sort'];
        //返回
        return $para;
    }

    /**
     * Desc : 自定义显示字段的页面标识
     * User : you name
     * Date : 2024-01-08 13:11
     * @return string
     */
    public function pageMark()
    {
        $pageStr = '';
        foreach (['cla', 'fun'] as $k) {
            $pageStr .= $this->get($k) ? $this->get($k) . '-' : '';
        }
        $pageStr = rtrim($pageStr, '-');
        return $pageStr;
    }

    /**
     * Desc : 列字段查询
     * User : you name
     * Date : 2024-01-22 12:00
     * @param string $pageStr
     * @return array|string[]
     */
    public function installSearch($pageStr = '')
    {
        $pageStr = $pageStr ?: $this->pageMark();
        $pageArr = explode('-', $pageStr);
        //默认显示字段
        $className = $pageArr[0] . 'Class';
        $class     = new (__NAMESPACE__ . '\\' . $className)();
        $default   = $class->fieldInit($pageArr[1]);

        // 查找自定义显示字段
        $userSetting = query('user_setting', generateWhere([
            'type' => '自定义显示字段',
            'page' => $pageStr,
            'stid' => self::$stid,
        ]), 'id, value');

        //初始化
        $result = ['page' => $pageStr];
        // 加载数据库配置
        if ($userSetting['id']) {
            $setting = json_decode($userSetting['value'], true);
        } else {
            $setting = $default;
        }
        //遍历
        foreach ((array)$setting as $key => $array) {
            //默认列名称存在才显示该列
            if (isset($default[$key]['name']) && (!isset($array['display']) || $array['display'])) {
                //先获取别名，不存在则获取默认列名称并替换多语言，表头名称需要附加其他标签或内容，通过text传递
                $name              = isset($array['alias']) ?
                    $array['alias'] :
                    (str_contains($default[$key]['name'], '{l.') ? parseLangTag($default[$key]['name']) : $default[$key]['name']);
                $name              .= isset($default[$key]['text']) ? $default[$key]['text'] : '';
                $result['key'][]   = $key;//列索引数组
                $result['head'][]  = $name;//列名称数组
                $result['width'][] = $array['width'];//列宽数组
                $result['sort'][]  = isset($default[$key]['sort']) ? $default[$key]['sort'] : 0;//是否需要排序数组
                $result['fix'][]   = isset($array['fix']) ? $array['fix'] : 0;//固定列
            }
        }
        //返回
        return $result;
    }

    /*列表页table拼接
	$data = array(
		"page" => "",//页面名称
		"head" => "",//表头
		"body" => "",//列表数据
		"button" => "",//左侧控件
		"width" => "",//列宽
		"orderBySign" => array(
			"head" => "",//
			"style" => "",//排序样式
		),
	);
	*/
    public function li($data)
    {
        //判断
        if (empty($data['install']['head'])) {
            $html = "表头不能为空";
        } elseif (empty($data['install']['width'])) {
            $html = "列宽不能为空";
        } else {
            $liHeight = isset($data['liHeight']) && $data['liHeight'] ? $data['liHeight'] : 32;
            //本表格ID
            $id          = suiji();
            $fixedColumn = []; //固定列数据
            //计算表体总宽度，含内边距。如果没有宽度，ul就只有显示区域的长度
            $width = 0;
            //计算表体总高度
            $height = (count($data['body']) - 1) * 35;
            //生成表头
            $head = "";
            foreach ($data['install']['head'] as $n => $value) {
                //查询是否附带有排序标签
                $sign = "";
                if (isset($data['orderBySign']['style']) && isset($data['orderBySign']['site']) && !empty($data['orderBySign']['style']) and $data['orderBySign']['site'] == $data['install']['key'][$n]) {
                    $sign = $data['orderBySign']['style'];
                }
                // 替换多语言标签
                if (str_contains($value, '{l.')) {
                    $value = parseLangTag($value);
                }
                $sortStr = $cursor = $keyStr = '';
                // 界面排序字段
                if ($data['install']['sort'][$n]) {
                    $cursor   = 'cursor';
                    $keyStr   = " li-sort-key ";
                    $sortSign = $ascSelected = $descSelected = '';
                    if (isset($data['orderBySign']['sort']) && $data['orderBySign']['sort'] && $data['orderBySign']['site'] == $data['install']['key'][$n]) {
                        $sortSign     = " sort = '" . $data['orderBySign']['sort'] . "' ";
                        $ascSelected  = $data['orderBySign']['sort'] == 'asc' ? 'table-sort-asced' : '';
                        $descSelected = $data['orderBySign']['sort'] == 'desc' ? 'table-sort-desced' : '';
                    }
                    $sortStr = '<span class="table-sort" ' . $sortSign . '><i class="table-sort-asc ' . $ascSelected . '"></i><i class="table-sort-desc ' . $descSelected . '"></i></span>';
                }
                if ($data['install']['fix'][$n]) {
                    $fixedColumn['key'][]   = $data['install']['key'][$n];
                    $fixedColumn['head'][]  = $value;
                    $fixedColumn['width'][] = $data['install']['width'][$n];
                    $fixedColumn['sort'][]  = $data['install']['sort'][$n];
                } else {
                    //生成单元格
                    $head  .= "
                        <li style='width:" . $data['install']['width'][$n] . "px' data-key='" . $data['install']['key'][$n] . "' " . $keyStr . ">
                            <span class='" . $cursor . "'>" . $value . $sign . "</span>
                            " . $sortStr . "
                            <span onmousedown='liWidth(this)' class='touch'>|</span>
                        </li>
                    ";
                    $width += $data['install']['width'][$n];
                }
            }
            //列名称设置控件
            $setting = $this->dominate(array(
                    "setting" => array("title" => "列名称设置", "click" => "layer('installSearch','home',{page:'" . $data['install']['page'] . "'})"))
            );
            //判断是否需序列号
            $serialShow = isset($data['page']['pageNow']);
            //判断是否需要合计
            $totalShow = (isset($data['total']) && count($data['total']) > 0 && count($data['body']) > 0);
            //排序号
            $serialDiv = "";
            if ($serialShow) {
                $serialHead = "<div class='button-control'>" . $setting . "</div>";
                $serialBody = "";
                foreach ($data['body'] as $k => $v1) {
                    $list       = ((int)$data['page']['pageNow'] - 1) * (int)$data['page']['pageNum'] + $k + 1;
                    $serialBody .= "<li  style='height:" . $liHeight . "px' class='serial-number'>" . $list . "</li>";
                }
                $totalSerial = $totalShow ? "<div class='buttonHead total-title'>" . lang('public.total') . "</div>" : "";
                $serialDiv   = "
                    <div class='left' style='width:auto'>
                        <div class='buttonHead'>" . $serialHead . "</div>
                        <div class='buttonBody'><ul>" . $serialBody . "</ul></div>
                        <div class='scrollLeft'></div>
                        " . $totalSerial . "
                    </div>
                ";
            }

            //生成控件区
            if (empty($data['button']['html'])) {
                $data['button']['width'] = 0;
                $buttonHead              = $buttonBody = "";
            } else {
                $buttonHead = "<div class='button-control'>" . $data['button']['html'][0] . ($serialShow ? '' : $setting) . "</div>";//控件区表头
                unset($data['button']['html'][0]);

                $buttonBody = "";//控件区表体
                if (count($data['button']['html']) > 0) {
                    foreach ($data['button']['html'] as $k => $b) {
                        $buttonBody .= "<li onclick='liButtonClick(this)' style='height:" . $liHeight . "px'><div class='button-control'>" . $b . "</div></li>";
                    }
                }
                //修正左侧控件区宽度
                if (!isset($data['button']['width']) || empty($data['button']['width'])) {
                    $data['button']['width'] = 70;
                }
            }
            //生成表体
            $body   = "";
            $noData = "";
            if (!is_array($data['body']) or count($data['body']) == 0) {
                $noData = "
                <div class='no-data-div'>
                    <img class='no-data-img' src='{$this->root}img/svg/noData.svg' >
                    <span class='no-data-text'>" . lang('homePage.nodata') . "</span>
                </div>
                ";
            } else {
                foreach ($data['body'] as $v1) {
                    $fixLi = [];
                    $li    = "";
                    foreach ($v1 as $n => $v2) {
                        $ondblclick = " title='双击单元格查看详情' ondblclick='lidbClick(this)' ";
                        if ($v2 === "" or $v2 === NULL) {
                            $v2         = "--";
                            $ondblclick = "";
                        }
                        if ($data['install']['fix'][$n]) {
                            $fixLi[] = $v2;
                        } else {
                            //$li .= "<li style='width:" . $data['install']['width'][$n] . "px' " . $ondblclick . "><span>" . $v2 . "</span></li>";
                            $li .= "<li style='width:" . $data['install']['width'][$n] . "px;height:" . ($liHeight) . "px' " . $ondblclick . ">" . $v2 . "</li>";
                        }
                    }
                    $fixedColumn['data'][] = $fixLi;
                    $body                  .= "<ul onclick='liClick(this)' style='width:" . $width . "px;height:" . $liHeight . "px'>" . $li . "</ul>";
                }
            }
            //列表合计
            $totalLeft = $totalRight = "";
            if ($totalShow) {
                $item = '';
                foreach ($data['install']['key'] as $n => $value) {
                    $text = isset($data['total'][$value]) ? $data['total'][$value] : '';
                    if ($data['install']['fix'][$n]) {
                        $fixedColumn['total'][] = $text;
                    } else {
                        $item .= "
                            <li style='width:" . $data['install']['width'][$n] . "px'>
                                " . $text . "
                            </li>
                        ";
                    }
                }
                if ($serialShow) {
                    $totalLeft = "<div class='buttonHead'></div>";
                } else {
                    $totalLeft = "<div class='buttonHead total-title'>" . lang('public.total') . "</div>";
                }
                $totalRight = "<div class='head'><ul style='width:" . $width . "px'>" . $item . "</ul><div class='scrollHead'></div></div>";
            }

            //组合固定列
            $fixDiv = "";
            if (isset($fixedColumn['key']) && count($fixedColumn['key']) > 0) {
                foreach ($fixedColumn['key'] as $n => $key) {
                    $sortStr = $cursor = $keyStr = '';
                    // 界面排序字段
                    if ($fixedColumn['sort'][$n]) {
                        $cursor   = 'cursor';
                        $keyStr   = " li-sort-key ";
                        $sortSign = $ascSelected = $descSelected = '';
                        if (isset($data['orderBySign']['sort']) && $data['orderBySign']['sort'] && $data['orderBySign']['site'] == $fixedColumn['key'][$n]) {
                            $sortSign     = " sort = '" . $data['orderBySign']['sort'] . "' ";
                            $ascSelected  = $data['orderBySign']['sort'] == 'asc' ? 'table-sort-asced' : '';
                            $descSelected = $data['orderBySign']['sort'] == 'desc' ? 'table-sort-desced' : '';
                        }
                        $sortStr = '<span class="table-sort" ' . $sortSign . '><i class="table-sort-asc ' . $ascSelected . '"></i><i class="table-sort-desc ' . $descSelected . '"></i></span>';
                    }
                    //生成表头单元格
                    $fixHead = "
                        <li style='width:" . $fixedColumn['width'][$n] . "px' data-key='" . $fixedColumn['key'][$n] . "' " . $keyStr . ">
                            <span class='" . $cursor . "'>" . $fixedColumn['head'][$n] . "</span>
                            " . $sortStr . "
                            <span onmousedown='fixLiWidth(this)' class='touch'>|</span>
                        </li>
                    ";
                    $fixBody = "";//控件区表体
                    foreach ($data['body'] as $k => $b) {
                        $value      = $fixedColumn['data'][$k][$n];
                        $ondblclick = " title='双击单元格查看详情' ondblclick=\"lidbClick(this,'fix')\" ";
                        if ($value === "" or $value === NULL) {
                            $value      = "--";
                            $ondblclick = "";
                        }
                        $fixBody .= "<li onclick='liButtonClick(this)' style='height:" . $liHeight . "px' " . $ondblclick . ">" . $value . "</li>";
                    }
                    //合计
                    $fixLeft = "";
                    if ($totalShow) {
                        $total   = "
                        <li style='width:" . $fixedColumn['width'][$n] . "px'>
                            " . $fixedColumn['total'][$n] . "
                        </li>
                    ";
                        $fixLeft = "<div class='buttonHead'><ul style='width:" . $fixedColumn['width'][$n] . "px'>" . $total . "</ul></div>";
                    }
                    $fixDiv .= "
                        <div class='left' style='width:" . ($fixedColumn['width'][$n]) . "px'>
                            <div class='buttonHead'><ul style='width:" . $fixedColumn['width'][$n] . "px'>" . $fixHead . "</ul></div>
                            <div class='buttonBody fixBody'><ul style='width:" . $fixedColumn['width'][$n] . "px'>" . $fixBody . "</ul></div>
                            <div class='scrollLeft'></div>
                            " . $fixLeft . "
                        </div>
                    ";
                }
            }

            //生成页面
            $html = "
    	    <div page='" . $data['install']['page'] . "' class='li' id='" . $id . "'>
    	        " . $serialDiv . "
    	        <div class='left' style='width:auto'>
        	        <div class='buttonHead'>" . $buttonHead . "</div>
        	        <div class='buttonBody'><ul>" . $buttonBody . "</ul></div>
        	        <div class='scrollLeft'></div>
        	        " . $totalLeft . "
    	        </div>
    	        " . $fixDiv . "
    	        <div class='right'>
    	            <div class='head'><ul style='width:" . $width . "px'>" . $head . "</ul><div class='scrollHead'></div></div>
    	            <div class='body' onscroll='liScroll(this)'>" . $body . "</div>
    	            " . $totalRight . "
    	        </div>
    	        " . $noData . "
            </div>
    	   <script>liWin('" . $id . "')</script>
    	    ";
        }
        //返回
        return $html;
    }

    /*列表页table拼接
    $data = array(
        "tr" => "字段数据",
        "text" => "按字段顺序添加td的附加说明或属性",
        "thead" => "为false表示不加tbody和thead标签",
        "table" => "为false表示不加table标签",
        "end" => "为true表示不展示空数据时的占位行，即‘一条记录也没有’行",
        "button" => "为true时，且end为true时，显示底部新增按钮",
        "method" => "新增按钮附带的方法名称",
        "orderBySign" => array(
            "site" => "排序位置",
            "style" => "排序样式",
        ),
        "displayFields" => false,
	    "showEmpty" => false //false:默认空值会以横杠填充，true:不填充
    );
    */
    public function tableMany($data): string
    {
        $data['showEmpty'] = $data['showEmpty'] ?? '';
        // 是否显示$thead
        $theadState = (!isset($data['thead']) || $data['thead'] !== false);
        // 页面标识
        $pageStr = '';
        foreach (['cla', 'fun'] as $k) {
            $pageStr .= $this->get($k) ? $this->get($k) . '-' : '';
        }
        $pageStr = rtrim($pageStr, '-');
        // 是否显示排序号
        $showSort = isset($data['showSort']) && $data['showSort'];
        // 表格合计
        $total = isset($data['total']) && is_array($data['total']) ? $data['total'] : []; //是否存在合计
        // 自定义表头（废弃）
        $status = false;
        //所有字段合集
        $fieldCollection = [];
        $pageFields      = null;
        $widths          = null;
        $fieldKes        = [];
        // 不显示fun 列表
        /*$status = $data['displayFields'] ?? !in_array($this->get('fun'),
                ['detail', 'edit', 'addTargetSearch', 'settingPage', 'addOrderMxSearch', 'addContractSearch', 'clueFileSearch', 'batchReport', 'addPickSearch',  'combination', 'materialTrack', 'qualityTrackSearch', 'addStockSearch', 'addPeopleSearch', 'addMaterialSearch', 'settingSearch', 'settedSearch', 'uploadList', 'addWaitPutInSearch', 'addSendOrderSearch', 'addSupplierPriceSearch', 'addQuotationsMxSearch', 'contractMxSearch']);*/

        // 查找自定义显示字段
        /*$userSetting = query('user_setting', generateWhere([
            'type' => '自定义显示字段',
            'page' => $pageStr,
            'stid' => self::$stid,
        ]), 'id, value');

        // 加载数据库配置
        if ($userSetting['id']) {
            $setting    = json_decode($userSetting['value'], true);
            $pageFields = $setting['field'];
            $widths     = $setting['width'];
        } else {
            $pageFields = null;
            $widths     = null;
        }*/

        //需要显示字段的序号
        $fieldKes = [];
        if (isset($data['tr'][0])) {
            foreach ($data['tr'][0] as $fKey => $title) {
                // 替换多语言标签
                if (str_contains($title, '{l.')) {
                    $title                = parseLangTag($title);
                    $data['tr'][0][$fKey] = $title;
                }
                if ($pageFields && in_array($title, $pageFields)) {
                    $fieldKes[] = $fKey;
                }
            }
        }
        array_unshift($fieldKes, 0);

        $first = $end = '';
        //检查最后一组是不是全是空的
        foreach ($data['tr'] as $key) {
            $firstValue = $key[0];
            if (!empty($firstValue)) {
                $first = "yes";
            }
            $endValue = end($key);
            if (!empty($endValue)) {
                $end = "yes";
            }
        }
        //组合table
        $row = $liStr = '';
        $x   = 0;
        foreach ($data['tr'] as $index => $key) {
            $td = "";
            if ($first != "yes" && (!isset($data['end']) || !$data['end'])) {
                array_shift($key);
            }
            if ($end != "yes" && (!isset($data['end']) || !$data['end'])) {
                array_pop($key);
            }
            $y = 0;
            foreach ($key as $no => $value) {
                //如果是表头，则查询是否附带有排序标签
                $orderBySign = "";
                if (empty($row)) {
                    if (!empty($data['orderBySign']['style']) and $data['orderBySign']['site'] == $y + 1) {
                        $orderBySign = $data['orderBySign']['style'];
                    }
                    //如果不是表头且本单元格为空，则补全空字段
                } elseif ($value === "" or $value === null) {
                    $value = $data['showEmpty'] ? '' : "---";
                }
                //返回本单元格
                if (isset($data['text'])) {
                    $td .= "<td " . ($data['text'][$x][$y] ?? null) . ">" . $value . $orderBySign . "</td>";
                } else {
                    $keyStr = $sortStr = '';
                    // 标题为空有html 标签部分不做排序
                    if ($value && $index === 0 && $no > 0 && $value == strip_tags($value)) {
                        $fieldCollection[] = $value;
                        $keyStr            = " sort-key='$value' ";
                        // 界面排序字段
                        $sortStr = '<span class="table-sort"><i class="table-sort-asc"></i><i class="table-sort-desc"></i></span><span class="drag">&nbsp;</span>';
                    }
                    // 先占位
                    if ($index === 0 && $no === 0 && $status && $theadState) {
                        $page  = hidden(['name' => 'page', 'value' => $pageStr]);
                        $value .= <<<EOT
							<img class="field-setting"  id="fieldSetting" src="{$this->root}img/control/setting.svg" alt="setting">
							$page
EOT;
                    }
                    // 过滤不显示内容
                    if ($status && $theadState) {
                        $width = '';
                        if ($no !== 0 && $index === 0) {
                            $width = !empty($widths[$value]) ? " width='$widths[$value]' " : '';
                            $value = '<span>' . $value . '</span>';
                        }
                        if ($pageFields !== null) {
                            if (in_array($no, $fieldKes)) {
                                $td .= "<td $keyStr $width>" . $value . $sortStr . $orderBySign . "</td>";
                            }
                        } else {
                            $td .= "<td $keyStr $width>" . $value . $sortStr . $orderBySign . "</td>";
                        }
                    } else {
                        $td .= "<td>" . $value . $orderBySign . "</td>";
                    }
                }
                $y++;
            }
            if ($x == 0 && $theadState) {
                //thead为false时，去掉thead和tbody
                $sortTitle = $data['sortTitle'] ?? '';
                $td        = $showSort ? "<td class='detail-list-number'>$sortTitle</td>" . $td : $td;
                $row       .= "<thead><tr>" . $td . "</tr></thead>";
            } else {
                $list = isset($data['page']) ? ((int)$data['page']['pageNow'] - 1) * (int)$data['page']['pageNum'] + $index : $index;
                $td   = $showSort ?
                    "<td class='detail-list-number'>
                        " . $list . "
                    </td>
                    " . $td :
                    $td;
                $row  .= "<tr onclick=\"tableManyClick(this)\">" . $td . "</tr>";
            }
            $x++;
        }
        // 替换占位符
        //$row = str_replace('{{litpl}}', $liStr, $row);
        if (count($data['tr']) == 1 && $theadState) {
            //thead为false时，去掉thead和tbody
            $row .= "<tbody>";
            $n   = $showSort ? count($data['tr'][0]) + 1 : count($data['tr'][0]);
            if (!isset($data['end']) || !$data['end']) {
                $row .= "<tr><td colspan='" . $n . "' class='no-data'>一条记录都没有</td></tr>";
            }
        }
        if (isset($data['end']) && isset($data['button']) && $data['button']) {
            $n   = count($data['tr'][0]);
            $row .= "<tr><td colspan='" . $n . "' class='add-line-button' style='text-align: center;cursor: pointer;font-weight: bold' onclick=\"{$data['method']}\">+&nbsp;新增</td></tr>";
        }
        if (count($data['tr']) == 1 && $theadState) {
            //thead为false时，去掉thead和tbody
            $row .= "</tbody>";
        }
        //合计
        if ($total) {
            $td = $showSort ? "<td>" . lang('public.total') . "</td>" : "";
            if (count($total) == count($data['tr'][0])) {
                foreach ($total as $k => $value) {
                    $value = $k == 0 && !$showSort && !$value ? lang('public.total') : $value;
                    $td    .= "<td>" . $value . "</td>";
                }
            } else {
                foreach ($data['tr'][0] as $k => $value) {
                    $value = isset($total[$k]) ? $total[$k] : ($k == 0 && !$showSort ? lang('public.total') : '');
                    $td    .= "<td>" . $value . "</td>";
                }
            }
            $row .= "<tfoot><tr>" . $td . "</tr></tfoot>";
        }
        if ((isset($data['thead']) && $data['thead'] === false) || (isset($data['table']) && $data['table'] === false)) {
            //table为false时，去掉table标签
            return $row;
        }

        return "<table class='tableMany' data-page='{$pageStr}' data-all='" . implode('[#]', $fieldCollection) . "'>" . $row . "</table>";
    }


    /*编辑页table拼接*/
    public function tableEdit($trArray)
    {
        $tr = '';
        foreach ($trArray as $tdArray) {
            $td = "";
            foreach ($tdArray as $key => $value) {
                if (count($tdArray) == 1) {
                    if (is_int($key)) {
                        $td .= "<td colspan='4'>" . $value . "</td>";
                    } else {
                        $td .= "<td>" . $key . "</td><td colspan='3'>" . $value . "</td>";
                    }
                } else {
                    $td .= "<td>" . $key . "</td><td>" . $value . "</td>";
                }
            }
            $tr .= "<tr>" . $td . "</tr>";
        }
        return "<table class='tableEdit'>" . $tr . "</table>";
    }

    /*弹出层列表样式
    $data = array(
        array(列
            "标题" => "内容",
            ...
        )...
    );
    */
    public function layerList($data)
    {
        //生成table
        $max = 0;
        foreach ($data as $array) {
            $num = count($array);
            if ($num > $max) {
                $max = $num;
            }
        }
        $ul = "";
        foreach ($data as $array) {
            //初始化参数
            $li    = "";
            $n     = 0;
            $liNum = count($array);
            //遍历数组
            foreach ($array as $key => $value) {
                //计数
                $n++;
                //如果单元格不足，则补全
                if ($liNum < $max and $liNum == $n) {
                    $m = ($max - $liNum) * 2 + 1;
                    if (is_int($key)) {
                        $m++;
                    }
                    $style = " style='flex:" . $m . ";' ";
                } elseif ($liNum == $max) {
                    $style = " style='flex:1;' ";
                } else {
                    $style = "";
                }
                // 替换多语言标签
                $value = parseLangTag($value);
                if (is_int($key)) {
                    //键名为整数时
                    $li .= "<li " . $style . ">" . $value . "</li>";
                } else {
                    $key = parseLangTag($key);
                    //打印本单元格
                    $key   = (str_contains($key, ':') || str_contains(
                            $key,
                            '：'
                        )) ? $key : ($key !== '&nbsp' ? $key . '：' : $key);
                    $title = strip_tags($key) !== $key ? '' : $key;
                    $li    .= "<li class='layer-line-title' title='$title'>" . $key . "</li><li " . $style . " class='layer-line-input'>" . $value . "</li>";
                }
            }
            $ul .= "<ul>" . $li . "</ul>";
        }
        //生成页面
        return "<div class='layerList'>" . $ul . "</div>";
    }

    /*弹出层编辑样式
    $data = array(
        "table" => "表单内容",
        "hidden" => "隐藏域",
        "button" => "表单控制按钮",//不填时生成标准提交按钮
        "formTwo" => "需要提交的第二个form表单名称",//非必填
    );
    */
    public function layerEdit($data)
    {
        //表单名称
        $form = $this->get('cla') . ucwords($this->get('fun')) . "Form";
        //拼接隐藏域
        $hidden = "";
        if (!empty($this->post('id'))) {
            $hidden .= hidden(["name" => "id", "value" => $this->post('id')]);//弹出层表单主索引
        }
        if (isset($data['hidden'])) {
            $hidden .= $data['hidden'];
        }
        //生成表单
        return "
		<form name='" . $form . "' onsubmit='return false'>
			" . $this->layerList($data['table']) . "
			<div class='hidden'>" . $hidden . "</div>
		</form>
		";
        //返回
    }

    /*自定义样式table拼接
    $data = array(
        "tr" => "字段数据",
        "text" => "按字段顺序添加td的附加说明或属性",
        "thead" => "为false表示不加tbody和thead标签",
        "table" => "为false表示不加table标签",
        "end" => "为true表示不展示空数据时的占位行，即‘一条记录也没有’行",
        "button" => "为true时，且end为true时，显示底部新增按钮",
        "method" => "新增按钮附带的方法名称",
        "page" => array(),//表格分页参数
        "total" => array(),//表格合计项
        "showSort" => false,//是否在首列展示排序号
        "class" => '', //表格class
	    "showEmpty" => false //false:默认空值会以横杠填充，true:不填充
    );
    */
    public function listTable($data): string
    {
        $data['showEmpty'] = $data['showEmpty'] ?? true;
        // 是否显示$thead
        $theadState = (!isset($data['thead']) || $data['thead'] !== false);
        // 是否显示排序号
        $showSort = isset($data['showSort']) && $data['showSort'];
        // 表格合计
        $total = isset($data['total']) && is_array($data['total']) ? $data['total'] : []; //是否存在合计
        // 替换多语言标签
        if (isset($data['tr'][0])) {
            foreach ($data['tr'][0] as $fKey => $title) {
                if (str_contains($title, '{l.')) {
                    $title                = parseLangTag($title);
                    $data['tr'][0][$fKey] = $title;
                }
            }
        }
        $row_num = count($data['tr']); //行数
        $col_num = $showSort ? count($data['tr'][0]) + 1 : count($data['tr'][0]); //列数

        $first = $end = '';
        //检查最后一组是不是全是空的
        foreach ($data['tr'] as $key) {
            $firstValue = $key[0];
            if (!empty($firstValue)) {
                $first = "yes";
            }
            $endValue = end($key);
            if (!empty($endValue)) {
                $end = "yes";
            }
        }
        //组合table
        $row = $liStr = '';
        $x   = 0;
        foreach ($data['tr'] as $index => $key) {
            $td = "";
            if ($first != "yes" && (!isset($data['end']) || !$data['end'])) {
                array_shift($key);
            }
            if ($end != "yes") {
                array_pop($key);
            }
            $y = 0;
            foreach ($key as $no => $value) {
                //如果不是表头且本单元格为空，则补全空字段
                if ($value === "" or $value === null) {
                    $value = $data['showEmpty'] ? '' : "---";
                }
                //返回本单元格
                if (isset($data['text'])) {
                    $td .= "<td " . ($data['text'][$x][$y] ?? null) . ">" . $value . "</td>";
                } else {
                    $td .= "<td>" . $value . "</td>";
                }
                $y++;
            }
            if ($x == 0 && $theadState) {
                //thead为false时，去掉thead和tbody
                $td  = $showSort ? "<td></td>" . $td : $td;
                $row .= "<thead><tr>" . $td . "</tr></thead>";
            } else {
                $list = isset($data['page']) ? ((int)$data['page']['pageNow'] - 1) * (int)$data['page']['pageNum'] + $index : $index;
                $td   = $showSort ?
                    "<td class='detail-list-number'>
                        " . $list . "
                    </td>
                    " . $td :
                    $td;
                $row  .= "<tr onclick=\"tableManyClick(this)\">" . $td . "</tr>";
            }
            $x++;
        }

        if ($row_num == 1 && $theadState) {
            //thead为false时，去掉thead和tbody
            $row .= "<tbody>";
            if (!isset($data['end']) || !$data['end']) {
                $row .= "<tr><td colspan='" . $col_num . "' class='no-data'>一条记录都没有</td></tr>";
            }
        }
        if (isset($data['end']) && isset($data['button']) && $data['button']) {
            $row .= "<tr><td colspan='" . $col_num . "' class='add-line-button' onclick=\"{$data['method']}\">+&nbsp;新增</td></tr>";
        }
        if ($row_num == 1 && $theadState) {
            //thead为false时，去掉thead和tbody
            $row .= "</tbody>";
        }
        //合计
        if ($total) {
            $td = $showSort ? "<td>合计</td>" : "";
            if (count($total) == count($data['tr'][0])) {
                foreach ($total as $k => $value) {
                    $value = $k == 0 && !$showSort && !$value ? "合计" : $value;
                    $td    .= "<td>" . $value . "</td>";
                }
            } else {
                foreach ($data['tr'][0] as $k => $value) {
                    $value = isset($total[$k]) ? $total[$k] : ($k == 0 && !$showSort ? "合计" : '');
                    $td    .= "<td>" . $value . "</td>";
                }
            }
            $row .= "<tfoot><tr>" . $td . "</tr></tfoot>";
        }
        if ((isset($data['thead']) && $data['thead'] === false) || (isset($data['table']) && $data['table'] === false)) {
            //table为false时，去掉table标签
            return $row;
        }
        $class = isset($data['class']) && $data['class'] ? $data['class'] : '';
        return "<table class='{$class}'>" . $row . "</table>";
    }

    /**
     * Desc : 编辑页带表格的页面组合
     * User : you name
     * Date : 2024-03-21 11:31
     * @param $data
     */
    public function editList($data)
    {
        $attribute = "";
        $class     = isset($data['class']) ? $data['class'] : '';
        $attribute .= " class='editList " . $class . "' ";
        if (isset($data['id'])) {
            $attribute .= " id='" . $data['id'] . "' ";
        }
        if (isset($data['other'])) {
            $attribute .= " " . $data['other'];
        }
        $title = '';
        if (isset($data['title'])) {
            if (isset($data['button'])) {
                $title .= "<div class='list-toolbar'><span class='smallTitle'>{$data['title']}</span>{$data['button']}</div>";
            } else {
                $title .= "<p>{$data['title']}</p>";
            }
        }
        $html = isset($data['html']) ? $data['html'] : '无';
        return "
                <div " . $attribute . ">
                    " . $title .
            $html . "
                </div>
                ";
    }

    /*编辑页列表样式
    $data = array(
        "title" => array(
            array(列
                "标题" => "内容",
                ...
            )...
        )...
    );
    */
    public function edit4($data)
    {
        //初始化
        $html = "";
        //获取表格最大列数
        $max = 0;
        foreach ($data as $oneKey => $oneValue) {
            if (is_array($oneValue)) {
                foreach ($oneValue as $twoKey => $twoValue) {
                    $num = count($twoValue);
                    if ($num > $max) {
                        $max = $num;
                    }
                }
            }
        }
        //数据分析
        foreach ($data as $oneKey => $oneValue) {
            //拼接编辑页
            if (is_array($oneValue)) {
                $ul = "";
                foreach ($oneValue as $twoKey => $twoValue) {
                    //初始化参数
                    $n     = 0;
                    $liNum = count($twoValue);
                    $li    = "";
                    //遍历数组
                    foreach ((array)$twoValue as $key => $value) {
                        if($key == 'attrHtml'){
                            $li.= $value;
                            continue;
                        }
                        //计数
                        $n++;
                        //如果单元格不足，则补全
                        if ($liNum <= $max and $liNum == $n) {
                            $m     = ($max - $liNum) + 1;
                            $style = " style='flex:" . $m . "' ";
                        } else {
                            $style = "";
                        }
                        // 替换多语言标签
                        $value = parseLangTag($value);
                        if (is_int($key)) {
                            //键名为整数时
                            $li .= "<li " . $style . ">" . $value . "</li>";
                        } else {
                            $key = parseLangTag($key);
                            //打印本单元格
                            $key = (str_contains($key, ':') || str_contains(
                                    $key,
                                    '：'
                                )) ? $key : ($key !== '&nbsp' ? $key . '：' : $key);
                            $li  .= "<li " . $style . ">
                                <div class='page-line-title'>" . $key . "</div>
                                <div style='flex: 1;' class='page-line-input'>" . $value . "</div>
                            </li>";
                        }
                    }
                    //拼接本行
                    $ul .= "<ul>" . $li . "</ul>";
                }
            } else {
                $ul = $oneValue; //非数组直接拼接字符串
            }
            //没有键名的数组，置为空
            if (is_int($oneKey)) {
                $oneKey = '';
            }
            if ($oneKey) {
                $oneKey = "<p>" . $oneKey . "</p>";
            }
            if ($oneValue) { //数组中有值才显示
                //拼接本表格
                $html .= "
                        <div class='edit4'>
                            " . $oneKey . $ul . "
                        </div>
                        ";
            }
        }
        //生成页面
        return $html;
    }

    /*编辑页单块独立
    $data = array(
        "title" => 'html'...
    );
    */
    public function editBlock($data)
    {
        //初始化
        $html = "";
        //数据分析
        foreach ($data as $oneKey => $oneValue) {
            //没有键名的数组，置为空
            if (!is_int($oneKey) && $oneKey) {
                $oneKey = "<p>" . $oneKey . "</p>";
            }
            if ($oneValue) { //数组中有值才显示
                //拼接本表格
                $html .= "
                        <div class='editBlock'>
                            " . $oneKey . $oneValue . "
                        </div>
                        ";
            }
        }
        //生成页面
        return $html;
    }

    /*页面编辑样式
    $data = array(
        "table" => "表单内容",
        "hidden" => "隐藏域",
    );
    */
    public function pageEdit($data)
    {
        //表单名称
        $form = $this->get('cla') . ucwords($this->get('fun')) . "Form";
        //拼接隐藏域
        $hidden = "";
        if (isset($data['hidden'])) {
            $hidden .= $data['hidden'];
        } elseif (!empty($this->get('id'))) {
            $hidden .= hidden(["name" => "id", "value" => $this->get('id')]);//弹出层表单主索引
        }
        $html = isset($data['table']) && $data['table'] ? $this->edit4($data['table']) : '';
        $html .= isset($data['html']) ? $data['html'] : '';
        //生成表单
        return "
		<form name='" . $form . "' onsubmit='return false'>
			" . $html . "
			<div class='center'>" . $hidden . "</div>
		</form>
		";
        //返回
    }

    /*选择全部/取消选择*/
    public function checkAll($formName, $checkName)
    {
        return "
        <label title='全选' class='listCheckbox'>
            <input type='checkbox' form='" . $formName . "' name='" . $checkName . "' onchange='checkAll(this)' />
            <span></span>
        </label>";
    }

    /*选择员工关联菜单
    $data = array(
        "show" => "显示层级：1、2、3、4",
        "class" => "样式",
        "departmentType" => "当前部门分类值",
        "department/job/staff" => array(
            "name" => "下拉菜单名称",
            "value" => "当前值",
        ),
    );
    */
    public function staffSelect($data)
    {
        $data['class']               = $data['class'] ?? null;
        $data['departmentType']      = $data['departmentType'] ?? null;
        $data['department']['value'] = $data['department']['value'] ?? '';
        //当前部门
        if (empty($data['department']['name'])) {
            $departmentName = "departmentId";
        } else {
            $departmentName = $data['department']['name'];
        }
        $departmentId = idSelect(array(
            "sqlForm"  => "department order by list ",
            "sqlId"    => "id",
            "sqlField" => "name",
            "name"     => $departmentName,
            "title"    => "当前部门",
            "class"    => $data['class'],
            "change"   => "getJob",
            "value"    => $data['department']['value'],
        ));
        //当前职位
        if (empty($data['job']['name'])) {
            $jobName = "jobId";
        } else {
            $jobName = $data['job']['name'];
        }
        if (empty($data['department']['value'])) {
            $JobId = select(
                array("name" => $jobName, "title" => "当前职位", "class" => $data['class'], "change" => "getStaff")
            );
        } else {
            $JobId = idSelect(array(
                "sqlForm"  => "job where departmentId = '" . $data['department']['value'] . "' order by list ",
                "sqlId"    => "id",
                "sqlField" => "name",
                "name"     => $jobName,
                "title"    => "当前职位",
                "class"    => $data['class'],
                "change"   => "getStaff",
                "value"    => $data['job']['value'],
            ));
        }
        //当前员工
        if (empty($data['staff']['name'])) {
            $staffName = "stid";
        } else {
            $staffName = $data['staff']['name'];
        }
        if (empty($data['staff']['title'])) {
            $staffTitle = "员工";
        } else {
            $staffTitle = $data['staff']['title'];
        }
        if (empty($data['staff']['value'])) {
            $stid = select(array("name" => $staffName, "title" => $staffTitle, "class" => $data['class'] ?? null));
        } else {
            $stid = idSelect(array(
                "sqlForm"  => "staff where jobId = '" . $data['job']['value'] . "' order by entryDay ",
                "sqlId"    => "stid",
                "sqlField" => "name",
                "name"     => $staffName,
                "title"    => "员工",
                "class"    => $data['class'],
                "value"    => $data['staff']['value'],
            ));
        }
        //拼接下拉菜单
        $html  = "";
        $array = array($departmentId, $JobId, $stid);
        foreach ($array as $key => $select) {
            if ($key < $data['show']) {
                $html .= $select;
            }
        }
        //返回
        return $html;
    }

    /**
     * 统计group by 的数据
     *
     * @param $sql
     * @return mixed
     */
    public function totalGroupNum($sql): mixed
    {
        $fullSql = "SELECT count(*) as total from ($sql) gropus";
        $result  = sqlFind($fullSql);
        if (isset($result[0]['total'])) {
            return $result[0]['total'];
        } else {
            if (static::is_null_array($result)) {
                return count(sqlFind($sql));
            }
            return 0;
        }
    }

    /**
     * 导入获取数据
     *
     * @param string $fileName
     * @param array $format
     * @return array
     */
    public function importHead(string $fileName = 'file', array $format = []): array
    {
        $tmp_name = $_FILES[$fileName]['tmp_name'];//临时文件名
        if (self::getExtension($_FILES[$fileName]['name']) !== 'xlsx') {
            return [];
        }
        $nameUrl1 = $nameUrl2 = '';
        if (PHP_OS == 'Linux') {
            $nameUrl2 = $tmp_name;
        } elseif (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
            //windows环境
            $num      = strripos($tmp_name, '\\');
            $nameUrl1 = substr($tmp_name, 0, $num); //缓存路径位置  C:\Users\Administrator\AppData\Local\Temp
            $nameUrl2 = substr($tmp_name, $num + 1);//文件名称  php1AE0.tmp
        }
        $config  = ['path' => $nameUrl1];
        $excel   = new \Vtiful\Kernel\Excel($config);
        $tempObj = $excel->openFile($nameUrl2)->openSheet(null, \Vtiful\Kernel\Excel::SKIP_EMPTY_ROW);
        if (!empty($format)) {
            $tempObj = $tempObj->setType($format);
        }
        $result = $tempObj->getSheetData();
        $data   = [];
        foreach ($result as $array) {
            if (!empty(array_filter($array))) {
                $data[] = $array;
            }
        }
        return array_filter($data);
    }


    /**
     * 组装sql
     *
     * @param $data
     * @return string
     */
    public function getSql($data): string
    {
        $where = '';
        if (empty($data['table'])) {
            $result = "数据库表名称为空";
        } else {
            //返回的字段
            if (empty($data['field'])) {
                if (!empty($data['sum'])) {
                    $data['field'] = " sum(" . $data['sum'] . ") as " . $data['sum'];
                } else {
                    $data['field'] = "*";
                }
            }
            //查询条件
            if (!empty($data['where'])) {
                $where = $data['where'];
            } elseif (!empty($data['single'])) {
                $where = $data['single'];
            }
            if (!empty($where)) {
                if (str_starts_with(trim($where), "and") or str_starts_with(trim($where), "order by") or empty($where)) {
                    $where = " 1=1 " . $where;
                }
                $where = " where " . $where;
            }
            //执行
            $result = "SELECT " . $data['field'] . " FROM " . $data['table'] . $where;
        }
        //返回
        return $result;
    }

    /*分页
    $data = array(
        "table" => "要查询的表名称",
        "where" => "查询条件",
        "order" => "排序方式",
        "pageNum" => "每页显示记录条数",
        "buttonNum" => "要显示的分页按钮数量",
    );
    */
    public function page(array $data)
    {
        $data['field'] = $data['field'] ?? '*';
        $data['order'] = $data['order'] ?? '';
        $data['union'] = $data['union'] ?? '';
        //修正每页显示的条数
        $pageStr     = $this->pageMark();
        $pageSetting = query('user_setting', generateWhere([
            'type' => '每页行数',
            'page' => $pageStr,
            'stid' => self::$stid,
        ]), 'id, value');
        if ($pageSetting['value'] && floatval($pageSetting['value']) > 0) {
            $data['pageNum'] = floatval($pageSetting['value']);
        } elseif (empty($data['pageNum']) or preg_match(checkInteger, $data['pageNum']) == 0) {
            $data['pageNum'] = (int)para('numberOfPageItems');
        }
        //修正分页按钮数量
        if (empty($data['buttonNum']) or preg_match(checkInteger, $data['buttonNum']) == 0) {
            $data['buttonNum'] = 7;
        }
        if (str_contains(strtolower(trim($data['table'] . $data['where'] . $data['order'])), 'group')) {
            //group by 查询方式
            $sql    = $this->getSql(
                array(
                    "table" => $data['table'],
                    "field" => $data['field'],
                    "where" => $data['where'] . ($data['order'] ? (" order by " . $data['order']) : ''),
                )
            );
            $sqlNum = $this->totalGroupNum($sql);
        } elseif ($data['union']) {
            //联表
            $sqlNum = static::total(array('debug' => $data['debug'] ?? '', 'sql' => "select ifnull(sum(a.num),0) as total from ({$data['union']}) as a")); //总条数
        } else {
            $sqlNum = static::total(array('table' => $data['table'], 'debug' => $data['debug'] ?? '', 'where' => $data['where'])); //总条数

        }
        $pageAll = is_numeric($sqlNum) ? ceil($sqlNum / $data['pageNum']) : exit($sqlNum);//总页数
        //修正当前页
        if ($this->get('page') > 1 and $this->get('page') <= $pageAll) {
            $pageNow = $this->get('page');
        } else {
            $pageNow = 1;
        }
        //判断要显示的第一个页码
        $pageCenter = ceil($data['buttonNum'] / 2);
        //底部分页按钮的居中页
        if ($pageNow <= $pageCenter) {//如果当前页小于等于居中页
            $pageFirst = 1;
        } elseif (($pageAll - $pageNow) <= $pageCenter) {  //如果当前页后面的页数小于等于居中页
            $pageFirst = $pageAll - $data['buttonNum'] + 1;//则把最后的几个页码显示出来
        } else {
            $pageFirst = $pageNow - $pageCenter;//如果当前页两边都有充足的页面，则居中显示
        }
        //拼接页码按钮
        $pageButton = "";
        for ($x = 0; $x < $data['buttonNum']; $x++) {
            $n = $pageFirst + $x;
            if ($n > 0 and $n <= $pageAll) {//$n可能小于零或大于总页数
                if ($n == $pageNow) {
                    $c = " class='pageNow' ";
                } else {
                    $c = "";
                }
                $pageButton .= "<li " . $c . " onclick=\"searchForm('" . $this->get('cla') . "','" . $this->get(
                        'fun'
                    ) . "'," . $n . ")\">" . $n . "</li>\n";
            }
        }
        //分页下拉菜单
        $option = "";
        if ($pageAll > 0) {
            for ($x = 1; $x <= $pageAll; $x++) {
                if ($pageNow == $x) {
                    $selected = " selected='selected' ";
                } else {
                    $selected = "";
                }
                $optionTitle = str_replace('{{x}}', $x, lang('public.page'));
                $option      .= "<option value='" . $x . "' " . $selected . ">$optionTitle</option>";
            }
        } else {
            $option .= "<option value='1'>" . lang('public.firstPage') . "</option>";
        }
        //分页html
        $pageLast = $pageNow <= 1 ? 1 : $pageNow - 1;
        //上一页
        $pageNext = $pageNow >= $pageAll ? $pageAll : $pageNow + 1;
        //下一页
        $pageHint         = str_replace(['{{sqlNum}}', '{{pageNow}}', '{{pageAll}}'], [$sqlNum, $pageNow, $pageAll], lang('public.pageHint'));
        $result['button'] = "
		<div class='page-content'>
            <div class='pageButton'>
                <ul>
                    <li onclick=\"searchForm('" . $this->get('cla') . "','" . $this->get('fun') . "',1)\">" . lang('button.firstPage') . "</li>
                    <li onclick=\"searchForm('" . $this->get('cla') . "','" . $this->get('fun') . "'," . $pageLast . ")\">" . lang('button.lastPage') . "</li>
                    " . $pageButton . "
                    <li onclick=\"searchForm('" . $this->get('cla') . "','" . $this->get('fun') . "'," . $pageNext . ")\">" . lang('button.nextPage') . "</li>
                    <li onclick=\"searchForm('" . $this->get('cla') . "','" . $this->get('fun') . "'," . $pageAll . ")\">" . lang('button.lastPageAll') . "</li>
                </ul>
                <select onchange=\"searchForm('" . $this->get('cla') . "','" . $this->get(
                'fun'
            ) . "',this.value)\">" . $option . "</select>
                <div class='left page-num-set'>
                    " . text(array(
                'name'  => '',
                'type'  => 'number',
                'class' => 'width50',
                'value' => $data['pageNum'],
                'other' => " data-page='$pageStr' min=1 max=100 onkeypress='if(event.which === 13) {pageSetInput(this);}' onblur='pageSetInput(this);' "
            )) . "<span>行/页</span>
                    <span class='hide red page-num-tip'></span>
                </div>
			</div>
			<div><span class='pageHint'>$pageHint</span></div>
		</div>
		";
        //数据库查询结果
        $sqlFirst = ($pageNow - 1) * $data['pageNum'];
        //当前页面开始位置
        $sqlTable       = find(
            array(
                "table" => $data['table'],
                "field" => $data['field'],
                "where" => $data['where'] . ($data['order'] ? (" order by " . $data['order']) : '') . " limit " . $sqlFirst . "," . $data['pageNum'],
            )
        );
        $result['para'] = [
            'pageAll' => $pageAll,
            'pageNum' => $data['pageNum'],
            'pageNow' => $pageNow,
        ];
        if (is_array($sqlTable)) {
            $result['sql']     = $sqlTable['sql'];
            $result['array']   = $sqlTable['array'];
            $result['fullSql'] = $this->interceptString($result['sql'], 'limit');
        } else {
            $result['sql']     = $sqlTable;
            $result['fullSql'] = $this->interceptString($result['sql'], 'limit');
            $result['array']   = [];
        }
        //提示
        $result['hint'] = "";
        //返回
        return $result;
    }

    /**
     * 截取指定字符串之前的字符
     *
     * @param $str       string 字符串
     * @param $searchStr string 指定字符
     * @return string
     */
    public function interceptString(string $str, string $searchStr): string
    {
        return str_replace(strchr($str, $searchStr), "", $str);
    }

    /*头部*/
    public function adHeader(array $onion, $page = '')
    {
        $imgSrc  = root . "img/control/clip.svg?v=" . version;
        $dingIco = '';
        if (count(array_filter($onion)) == 4) {
            $selected = "";
            $title    = "设置桌面快捷入口";
            if (in_array($page, homepageClass::getUserQuick())) {
                $selected = "clip-selected";
                $title    = "取消桌面快捷入口";
            }
            $dingIco = "<img title='$title' onclick=\"setQuick(this,'$page')\" class='ding-clip $selected' src='$imgSrc'>";
        }
        $url     = para("name");
        $company = query('company', "coid = '" . self::$coid . "'");
        array_unshift($onion, $this->control['name']);
        array_unshift($onion, $company['name']);
        $onion = self::filterNull($onion);
        foreach ($onion as $value) {
            $url .= "&nbsp;>&nbsp;" . $value;
        }
        $parms = http_build_query($this->get);
        return "
        <div id='header'>
            <div id='renovate' onclick='reloadPage(this)' url='" . root . "control/adIndex.html?" . $parms . "'><img title='刷新' src='" . root . "img/control/renovate.svg'></div><div class='onion'>" . $dingIco . "<span>{$url}</span></div>
        </div>
        
		<div id='body'>
		";
    }

    /*底部*/
    public function adFooter()
    {
        return "
				</div>
			</body>
		</html>";
    }


    /**
     *  查询条件
     *
     * @param string $html 查询表单
     * @param string|null $type 类型
     * @param string $otherButton
     * @param string $cla
     * @param string $fun
     * @param string $layout
     * @param string $toolButton
     * @param string $searchOption
     * @param string $resetFun
     * @param bool $isSearch
     * @return string
     */
    public function search(string $html, string $type = null, string $otherButton = '', string $cla = '', string $fun = '', string $layout = '', string $toolButton = '', string $searchOption = '{}', string $resetFun = '', bool $isSearch = true)
    {
        //异步调用数据的函数名称
        $fun = $fun ?: $this->get('fun') . "Search";
        $cla = $cla ?: $this->get('cla');
        return $this->searchExecute([
            'cla'          => $cla,
            'fun'          => $fun,
            'html'         => $html,
            'otherButton'  => $otherButton,
            'type'         => $type,
            'layout'       => $layout,
            'toolButton'   => $toolButton,
            'searchOption' => $searchOption,
            'resetFun'     => $resetFun,
            'isSearch'     => $isSearch,
        ]);
    }

    /**
     * search执行
     */
    public function searchExecute($data)
    {
        //异步调用数据的函数名称
        $fun                  = $data['fun'] ?? $this->get('fun') . "Search";
        $cla                  = $data['cla'] ?? $this->get('cla');
        $resetFun             = isset($data['resetFun']) && $data['resetFun'] ? $data['resetFun'] : $this->get('fun') . "Options";
        $data['type']         = $data['type'] ?? '';
        $data['otherButton']  = $data['otherButton'] ?? '';
        $data['layout']       = $data['layout'] ?? '';
        $data['toolButton']   = $data['toolButton'] ?? '';
        $data['searchOption'] = $data['searchOption'] ?? '{}';
        $light                = '';
        if ($data['type'] === null) {
            $light = '<div class="space bg-light-grey"></div>';
        } elseif ($data['type'] == 'menu') {
            $light = '<style>#homeSearchHtml, [searchformhtml]{padding: 0;margin-left: 10px;}</style>';
        }
        if ($data['otherButton'] === 'no') {
            $light = '';
        }
        $search_fun = "searchForm('" . $cla . "','" . $fun . "', 1)";
        if (isset($data['option']) && $data['option']) {
            $search_fun = "searchForm('" . $cla . "','" . $fun . "', 1,true, $data[option])";
        }
        $js          = "<script>$(function(){{$search_fun}});</script>";
        $hide        = $data['otherButton'] === 'no' ? 'hide' : '';
        $otherButton = $data['otherButton'] === 'no' ? '' : $data['otherButton'];
        $sort        = $this->defaultSort(); //默认排序
        $soryHidden  = hidden(['name' => 'list_sort_key', 'value' => $sort['list_sort_key']]) . hidden(['name' => 'list_sort', 'value' => $sort['list_sort']]);
        //查询表单处理
        if ($data['layout'] == 'pop') {
            $search = "
                <div class='list-top' searchformhtml='" . $fun . "Html'>
                    <div class='top-left'>
                        <div class='left-search'>
                            <div class='search-switch'>查询</div>
                            <div class='search-container'>
                                <div class='search-back'></div>
                                <div class='search-div'>
                                    <form name='" . $fun . "Form' onsubmit=\"$search_fun;return false;\">
                                        <div class='search-input-list'>
                                            " . $data['html'] . "
                                        </div>
                                        <div class='search-hidden'>" . $soryHidden . "</div>
                                        <div class='search-buttons'>
                                            <input class='layer_search_button' type='submit' value='" . lang('button.search') . "'>
                                            <span class='cancel-button'>取消</span>
                                            <span class='reset-button' onclick=\"searchResetting(this, '" . $cla . "','" . $resetFun . "', $data[searchOption]);\">重置</span>
                                            {$otherButton}
                                        </div>
                                    </form>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class='top-right'>
                        <div class='right-button'>
                            {$data['toolButton']}
                        </div>
                    </div>
                </div>
                ";
            $js     .= "<script>
                /**列表查询弹窗事件**/
                $('.list-top').on('click', '.left-search', function (){
                    $(this).find('.search-container').show();
                })
                $(document).on('click', '.layer_search_button,.cancel-button,.search-back', function(event) {
                    $(this).parents('.search-container').hide();
                });
            </script>";
        } else {
            $isSearch = "";
            if($data['isSearch']){
                $isSearch = "<input class='layer_search_button' type='submit' value='" . lang('button.search') . "'>";
            }
            $search = "
                <div class='search $hide' searchformhtml='" . $fun . "Html'>
                    <form name='" . $fun . "Form' onsubmit=\"$search_fun;return false;\">
                        " . $data['html'] . $soryHidden . "
                        {$isSearch}
                        {$otherButton}
                    </form>
                </div>";
        }
        return "
            $search
            $light
            <div id='" . $fun . "Html' searchformhtml='" . $fun . "Html'>" . lang('public.dataQueryIng') . "</div>
            $js
		";
    }

    /**
     * Desc : 列表默认排序字段
     * User : you name
     * Date : 2024-05-28 17:50
     * @param string $pageStr
     * @return array
     */
    public function defaultSort($pageStr = ''): array
    {
        $pageStr = $pageStr ? $pageStr . 'Search' : $this->pageMark() . 'Search';
        // 查找自定义显示字段
        $userSetting = query('user_setting', generateWhere([
            'type' => '自定义显示字段',
            'page' => $pageStr,
            'stid' => self::$stid,
        ]), 'id, value');
        $sort        = ['list_sort_key' => '', 'list_sort' => ''];
        // 加载数据库配置
        if ($userSetting['id']) {
            $setting = json_decode($userSetting['value'], true);
            //遍历
            foreach ((array)$setting as $key => $array) {
                // 是否存在默认排序
                if (!empty($array['list_sort'] ?? '')) {
                    $sort['list_sort_key'] = $key;
                    $sort['list_sort']     = $array['list_sort'];
                    break;
                }
            }
        }
        //返回
        return $sort;
    }


    /**
     * 页面权限检查
     *
     * @return array
     */
    public function homePower(): array
    {
        //页面名称
        $key  = '';
        $name = '';
        if (empty($this->get('cla'))) {
            $warn = "类名称为空";
        } elseif (empty($this->get('fun'))) {
            $warn = "类的方法名称为空";
        } else {
            foreach ($this->powerAll as $all) {
                foreach ($all as $oneArray) {
                    foreach ($oneArray as $twoArray) {
                        foreach ($twoArray as $threeKey => $threeArray) {
                            if (isset($threeArray['cla']) and $this->get('fourKey') == $threeKey and ($threeArray['cla'] == $this->get('cla') and $threeArray['fun'] == $this->get('fun'))) {
                                $key  = $threeKey;
                                $name = $threeArray['name'];
                            } else if (empty($threeArray['cla']) and empty($threeArray['fun']) and $this->get('cla') == $threeKey) {
                                $key  = $threeKey;
                                $name = $threeArray['name'];
                            }
                        }
                    }
                }
            }
        }
        //权限判断
        if (empty($key)) {
            $warn = "需要打开的页面名称为空";
        } elseif (!in_array($key, array_keys($this->controlPower))) {
            $warn = "你没有打开《" . $name . "》页面的权限";
        }
        //跳转
        if (!empty($warn)) {
            $_SESSION['warn'] = $warn;
            header("location:" . root . "control/adIndex.html?cla=homepage&fun=home");
            exit(0);
        }
        //返回
        return ["key" => $key, "name" => $name];
    }

    /**
     * 搜索框
     *
     * @param $data
     * @return string
     */
    public static function searchText($data): string
    {
        $attribute = $js = "";
        if (isset($data['id'])) {
            $attribute .= " id='" . $data['id'] . "' ";
        } elseif (array_key_exists("laydate", $data)) { //如果存在laydate键名
            $id        = suiji();
            $attribute .= " id='" . $id . "' ";
            $json      = "";
            foreach ((array)$data['laydate'] as $key => $value) {
                if (in_array($key, ['done', 'ready', 'change', 'mark'])) {
                    $json .= "," . $key . ":" . $value;
                } else {
                    $json .= "," . $key . ":'" . $value . "'";
                }
            }
            $js = "<script>$(function(){laydate.render({elem:'#" . $id . "'" . $json . ", trigger:'click'});});</script>";
        }
        if (isset($data['title']) && $data['title']) {
            $attribute .= "  placeholder='" . $data['title'] . "' title='" . $data['title'] . "' ";
        }
        if (isset($data['value']) && mb_strlen($data['value'], 'utf8') > 0) {
            $attribute .= " value='" . $data['value'] . "' ";
        }
        $data['class'] = $data['class'] ?? '';
        $data['click'] = $data['click'] ?? '';
        $data['class'] = "search-text " . $data['class'];
        if (isset($data['unit'])) {//单位
            $data['class'] .= " layui-input form-control";
        }
        if ($data['class']) {
            $attribute .= " class='" . $data['class'] . "' ";
        }
        // 自定义data 参数
        if (isset($data['data']) && is_array($data['data'])) {
            foreach ($data['data'] as $key => $value) {
                $key       = trim($key);
                $value     = trim($value);
                $attribute .= " data-{$key}='{$value}' ";
            }
        }
        // 支持的类型
        $keys  = ['blur', 'change', 'keyup'];
        $array = array_intersect($keys, array_keys($data));
        foreach ($array as $key) {
            $temp = explode(',', $data[$key]);
            // 统计个数
            $length    = count($temp);
            $attribute .= ' on' . $key . '="' . $temp[0] . "(this";
            if ($length > 1) {
                for ($i = 1; $i < $length; $i++) {
                    $temp[$i]  = trim(str_replace(['\'', '"'], '', $temp[$i]));
                    $attribute .= ", '$temp[$i]'";
                }
            }
            $attribute .= ')"';
        }
        $type  = $data['type'] ?? 'text';
        $other = $data['other'] ?? '';
        $html  = "<input type='{$type}' name='{$data['name']}' autocomplete='off' " . $attribute . $other . ">" . $js;
        if (isset($data['unit'])) {
            //带单位的输入框
            $html = "<div class='input-group'>" . $html . " <span class='input-group-addon'>{$data['unit']}</span></div>";
        } elseif (isset($data['search'])) {
            $html = "<span class='right interval' >" . $html . "<span onclick=\"{$data['click']}\" class='background-color-gray'><img alt='' src='" . root . "img/control/search.svg'></span></span>";
        }
        $html .= <<<efo
<style>
  .search-text{
     height: 19px;padding: 2px 4px;border-top-left-radius:2px;border-bottom-left-radius:2px;
  }
  .background-color-gray{
    margin: 0;padding:3px 10px;cursor: pointer;
  }
  .interval{
    margin-right: 10px;
  }
</style>
efo;

        return $html;
    }

    /*导入按钮
    $data = array(
        "title" => "按钮标题",
        "fun" => "导入分析函数",
    );
    */
    public function upButton($data): string
    {
        //表单名称
        $form        = self::getId() . "UpForm";
        $buttonClass = isset($data['buttonClass']) ? $data['buttonClass'] : 'spanButton';
        //HTML内容
        return <<<EOT
<span class='{$buttonClass}' onclick="document.{$form}.file.click()">{$data['title']}</span>
<form name='{$form}'  class='hide' method='post' enctype='multipart/form-data' action='{$this->root}control/adIndex.html?cla={$this->get(
            'cla'
        )}&fun={$data['fun']}'>
			<input name='file' type='file' onchange='document.{$form}.submit()'>
		</form>
EOT;
    }

    /**
     * 入口页函数
     *
     * @param string $html "查询表单";
     * @return string
     */
    public function homeFun(string $html)
    {
        //页面权限
        $homePower = $this->homePower();
        //洋葱皮
        $oneName = $twoName = $threeName = $fourName = '';
        foreach ($this->powerAllLang as $oneKey => $twoArray) {
            foreach ($twoArray as $twoKey => $threeArray) {
                foreach ($threeArray as $threeKey => $fourArray) {
                    if (array_key_exists($homePower['key'], $fourArray)) {
                        $oneName   = $oneKey;
                        $twoName   = $twoKey;
                        $threeName = $threeKey;
                        $fourName  = $fourArray[$homePower['key']]['name'];
                        break;
                    }
                }
            }
        }
        $onion = array($oneName, $twoName, $threeName, $fourName);
        //返回
        return head("ad") . $this->adHeader($onion, $homePower['key']) . $html . warn() . $this->adFooter();
    }

    /**
     * 根据页面权限返回导航条
     */
    public function getOnion()
    {
        //页面权限
        $homePower = $this->homePower();
        //洋葱皮
        $oneName = $twoName = $threeName = $fourName = '';
        foreach ($this->powerAllLang as $oneKey => $twoArray) {
            foreach ($twoArray as $twoKey => $threeArray) {
                foreach ($threeArray as $threeKey => $fourArray) {
                    if (array_key_exists($homePower['key'], $fourArray)) {
                        $oneName   = $oneKey;
                        $twoName   = $twoKey;
                        $threeName = $threeKey;
                        $fourName  = $fourArray[$homePower['key']]['name'];
                        break;
                    }
                }
            }
        }
        return array($oneName, $twoName, $threeName, $fourName);
    }

    /*详情页~页卡
    $data = array(
        "id" => "切换内部页卡和当前提交表单时的ID",
        "title" => "洋葱皮最后一级导航，有onion参数时可不填本参数",
        "button" => "当前表单提交按钮标题",
        "onion" => "定义全部洋葱皮导航，非必填",
        "menu" => array(
            "菜单关键词" => "菜单标题",  //需要调用的函数在当前类时的简写
            "菜单关键词" => array(     //需要调用其他类方法时的写法
                "name" => "菜单标题",
                "cla" => "类名称",
                "fun" => "类的方法名称",
            ),

        ),
        "power" =>  页面权限
    );
    */
    public function tab(array $data)
    {
        $html = $form = "";
        //页面权限
        if (isset($data['power']) && $data['power'] !== false) {
            $this->homePower();
        }
        $data['pageType'] = $data['pageType'] ?? '';
        //生成导航
        if (isset($data['menu']) && $data['menu']) {
            $li = "";
            foreach ($data['menu'] as $key => $value) {
                if (empty($li)) {
                    $hover = " class='pageMenuHover' ";
                } else {
                    $hover = "";
                }
                if (is_array($value)) {
                    $tabName   = $value['name'];//页卡中文名称
                    $className = $value['cla']; //调用的类的名称
                    $fun       = $value['fun']; //调用的方法的名称
                } else {
                    $tabName   = $value;
                    $className = $this->get('cla');
                    $fun       = $key;
                }
                $li .= "<li pageMenu='" . $fun . "' onclick=\"detailTab('" . $className . "','" . $fun . "','" . $data['id'] . "','{$data['pageType']}')\" " . $hover . ">" . $tabName . "</li>";
                //如果GET menu为当前页卡
                if ($this->get('menu') == $fun) {
                    $html .= "<script>$(function(){detailTab('" . $className . "','" . $fun . "','" . $data['id'] . "','{$data['pageType']}')});</script>";
                }
            }
            $html .= "
			<div id='pageMenu'>
			<ul>" . $li . "</ul>
			<div class='clear'></div>
			</div>
			";
        }

        //洋葱皮
        if (!isset($data['onion']) || !$data['onion']) {
            $data['onion'] = [];
            $data['title'] = $data['title'] ?? '';
            $data['name']  = $data['name'] ?? $data['title'];
            $oneName       = $twoName = $threeName = $threeHref = $fourName = '';
            //洋葱皮
            foreach ($this->powerAll as $oneKey => $oneArray) {
                foreach ($oneArray as $twoKey => $twoArray) {
                    foreach ($twoArray as $threeKey => $threeArray) {
                        $className = $this->get('cla');
                        if (array_key_exists($className, $threeArray)) {
                            //三级导航数组
                            $threeArray = $threeArray[$className];
                            //三级导航链接
//                            if (!isset($threeArray['cla']) or !$threeArray['cla'] or !isset($threeArray['fun']) or !$threeArray['fun']) {//如果没有定义类或函数名称，则使用模块名称作为类名称
//                                $iframeHref = root . "control/adIndex.html?cla=" . $className . "&fun=home";
//                            } else {
//                                $iframeHref = root . "control/adIndex.html?cla=" . $threeArray['cla'] . "&fun=" . $threeArray['fun'];
//                            }
                            // 一级菜单
                            $oneName = $oneKey;
                            // 二级菜单
                            $twoName   = $twoKey;
                            $threeName = $threeKey;

                            $fourName = (isset($data['name']) && $data['name']) ? $data['name'] : $threeArray['name'];
                            //三级导航
                            $threeHref = "<span>" . $threeArray['name'] . "</span>";
                            break;
                        }
                    }

                }
            }
            $fourTitle = match ($this->get('fun')) {
                'edit','editPage' => '编辑',
                'detail' => '详情',
                default              => '',
            };
            // 四级
            $fourName      = ($this->get('fun') == 'home') ? null : ((isset($data['name']) && $data['name']) ? $fourName : $fourName . $fourTitle);
            $data['onion'] = [$oneName, $twoName, $threeName, $threeHref, $fourName];
        }
        //定义初始页卡的表单
        if (isset($data['tr']) && is_array($data['tr']) and count($data['tr']) > 0) {
            //生成表单
            $form = "
			<form name='" . $this->get('fun') . "Form'>
				" . $this->tableEdit($data['tr']) . "
				<input name='id' type='hidden' value='" . getVal($data, 'id') . "'>
			</form>
			";
        }
        //第一个页卡的关键词
        if (empty($data['menu'])) {
            $pageDiv = $this->get('fun');
        } else {
            $pageDiv = key($data['menu']);
        }

        $formButton = '';
        if (isset($data['button']) && $data['button']) {
            $formButton = "<div class='tab-button'>" . $data['button'] . "</div>";
        }
        //生成页卡
        if (isset($data['pageType']) && $data['pageType'] == 'list') {
            $html .= "
		<div class='pageDiv' pageDiv='" . $pageDiv . "'>
			" . $form . ($data['html'] ?? null) . clear . "
		</div>";
        } else {
            $html .= "
		<div class='pageDiv' pageDiv='" . $pageDiv . "'>
		    <div class='tab-box'>
		        $formButton
		        <div class='tab-content'>
			" . $form . ($data['html'] ?? null) . clear . "
			    </div>
			</div>
		</div>";
        }

        $data['header'] = $data['header'] ?? '';
        if ($data['header'] === false) {
            return $html;
        }
        $form = $this->get('cla') . ucwords($this->get('fun')) . "Form";

        $js = <<<EOT

		<script>
		const cla = '{$this->get('cla')}', fun = '{$this->get('fun')}', formName = '$form'
		// getTemp(cla, fun, formName)
		</script>
EOT;
        //返回
        return head("ad") . $this->adHeader($data['onion'], $this->get('cla')) . $html . $js . warn() . $this->adFooter();
    }

    /*弹出层
    $data = array(
        "title" => "标题",
        "height" => "高度",
        "width" => "宽度",
        "zindex" => "弹出层堆叠顺序",//非必填
        "html" => "内容",
    );
    */
    public function layer($data)
    {
        $dibianZ = $winZ = '';
        //弹出层HTML ID
        $json['id'] = $this->get('cla') . ucwords($this->get('fun'));
        //定义弹出层堆叠顺序
        if (!empty($data['zindex'])) {
            $dibianZ = "z-index:" . ($data['zindex'] - 1) . ";";
            $winZ    = "z-index:" . $data['zindex'] . ";";
        }
        //默认宽度，此为经调试后弹出层双列表单的最优宽度
        if (empty($data['width'])) {
            $data['width'] = 900;
        }

        if (empty($data['winFix'])) {
            $winFix = "class='winAuto'";
        } else {
            $winFix = '';
        }
        if (isset($data['remove'])) {
            $close = "<span onclick=\"$('#" . $json['id'] . "').remove()\" class='winClose'>×</span>";
        } else {
            $close = "<span onclick=\"$('#" . $json['id'] . "').hide()\" class='winClose'>×</span>";
        }
        if (isset($data['notClose']) && $data['notClose']) {
            $close = "";
        }
        //表单名称
        $form = $this->get('cla') . ucwords($this->get('fun')) . "Form";
        //生成提交按钮
        $footHeight = 40;
        if (isset($data['button']) && $data['button']) {
            $winFoot = "<div class='winFoot'>" . $data['button'] . "</div>";
        } else {
            if (empty($data['formTwo'])) {
                $subForm = $form;
            } else {
                $subForm = $form . "," . $data['formTwo'];
            }
            $url     = root . "control/adIndex.html?cla=" . $this->get('cla') . "&fun=" . $this->get('fun') . "Edit";
            $winFoot = "<div class='winFoot'>
                            <input onclick=\"subForm('" . $subForm . "','" . $url . "')\" type='button' class='button' value='" . L('button.ConfirmSubmit') . "'>
                        </div>";
        }
        if (isset($data['button']) && $data['button'] === false) {
            $footHeight = 0;
            $winFoot    = "";
        }
        //弹出层框架
        $json['html'] = "
		<div class='dibian' style='" . $dibianZ . "'></div>
		<div class='win' style='height:" . $data['height'] . "px; width:" . $data['width'] . "px; margin:-" . ceil(
                $data['height'] / 2
            ) . "px 0px 0px -" . ceil($data['width'] / 2) . "px;" . $winZ . "'>
			<div class='winTitle'>" . parseLangTag($data['title']) . $close . "</div>
			<div {$winFix} style='height:" . ($data['height'] - 40 - $footHeight) . "px;'>" . $data['html'] . "</div>
			" . $winFoot . "
		</div>
		";
        //返回
        return json_encode($json, 320);
    }

    /**
     * 获取当前员工的当前部门和所有上级部门，当前职位，当前员工ID组合
     */
    public function staffCombination($isString = false, $stid = ''): array|string
    {
        if ($stid) {
            $staff  = query('staff', "stid = '$stid'");
            $result = [
                $stid,
                $staff['jobId'],
            ];
            $job    = query('job', "id = '$staff[jobId]'");
            $this->departmentCom($job['departmentId'], $departmentId);
        } else {
            $result = [
                self::$stid,
                $this->controlJob['id'],
            ];
            $this->departmentCom($this->controlJob['departmentId'], $departmentId);
        }
        $result = array_merge($result, $departmentId);
        return $isString ? implode(',', $result) : $result;
    }

    /**
     * 获取部门集合
     */
    private function departmentCom($departmentId, &$arr)
    {
        $arr[]            = $departmentId;
        $department       = query('department', "id = '$departmentId'");
        $departmentParent = query('department', "id = '$department[pid]'");
        if (!empty($departmentParent['id'])) {
            $this->departmentCom($departmentParent['id'], $arr);
        }
        return $arr;
    }

    /*框架*/
    public function frame(): string
    {
        $userMenu = self::$user['menu'] ?: '个人中心';
        // 红点标记
        $userNote = $this->getMarkNum('合计') > 0 ? '<span class="user-note"></span>' : '';
        $menu     = $this->getframeLeft();
        // 系统提示信息
        $systemTipMessage       = '';
        $systemTipMessageSwitch = para('systemTipMessageSwitch');
        if ($systemTipMessageSwitch != 3) {
            $tipScript = <<<EOT
           <script>
			let objArr = ['#iframeTop', '#frameLeft', '#frameRight']
			function locadTip(objArr, direction='+'){
			    for (let obj of objArr ) {
			      let top = parseFloat($(obj).css('top'))
			      top = (direction === '+') ? top + 40 : top - 40
			      if(obj === '#iframeTop'){
			          let array = []
			          $(obj).children().each(function(){
			             const id = $(this).attr('id')
			             if(id){
			                array.push('#'+id)
			             }
			          })
			          if(array.length > 0){
			            locadTip(array, direction)
			          }
			      }
			      $(obj).css('top', top +'px')
			    }
			}
			$(function(){
				locadTip(objArr)
			})
			</script>
EOT;
            if ($systemTipMessageSwitch == 1) {
                $systemTipMessage = '<div id="systemTipMessage" class="system-tip-message">' . para('systemTipMessage') . '<span onclick="$(\'#systemTipMessage\').hide();locadTip(objArr, \'-\')" class="tip-close">X</span></div>' . $tipScript;
            } elseif ($systemTipMessageSwitch == 2) {
                $systemExpirationDate = para('systemExpirationDate');  //到期日期
                $dateEndTime          = strtotime($systemExpirationDate) + 86400;
                $days                 = intval(($dateEndTime - time()) / 86400);
                if ($days > 0) {
                    $message          = str_replace(['{{day}}'], ["<span class='red'>{$days}</span>"], para('systemTipCountdown'));
                    $systemTipMessage = '<div id="systemTipMessage" class="system-tip-message">' . $message . '<span onclick="$(\'#systemTipMessage\').hide();locadTip(objArr, \'-\')" class="tip-close">X</span></div>' . $tipScript;
                } else {
                    $systemTipMessage = '<div id="systemTipMessage" style="height: 100% !important;" class="system-tip-message"><span class="red">系统已到期，请联系系统管理员</span></div>' . $tipScript;
                }
            }
        }
        //页面
        //返回
        return head("ad") . $systemTipMessage . "
        <div id='iframeTop'>
			<img id='adLogo' onclick=\"href('control/adIndex.html')\" src='" . img('logoConrolImg') . "'>
			<div id='iframeTitleBack' class='iframeTitleBack'></div>
			<div id='shrink' onclick='shrink(this)'><img title='隐藏左侧菜单' src='" . root . "img/control/moveLeft.svg'></div>
			<div id='homepage' class='iframeTitleNow' onclick=\"homepage()\"><img title='主页' src='" . root . "img/control/homepage.svg'></div>
	        <div id='pageLeft' onclick='pageLeft()'><img src='" . root . "img/control/pageLeft.svg'></div>
	        <div id='iframeTitle'><ul></ul></div>
			<div id='pageRight' onclick='pageRight()' style='right: 101px'><img src='" . root . "img/control/pageRight.svg'></div>
			<div id='language' title='" . lang('switchLang') . "'><img src='" . root . "img/control/language.svg'></div>
			<div id='searchMenu' onclick='searchMenu()' title='" . lang('menuSearch.title') . "'><img  src='" . root . "img/control/search.svg'>
			<div id='searchMenuText' class='animated fadeInRight' ><input id='searchMenuInput' type='text' autocomplete='off' placeholder='" . lang('menuSearch.placeholder') . "'><i class='container-left-search-ico' style='top: 10px;right: 10px;margin: 0'></i></div>
			</div>
	        <div id='user'><img src='" . root . "img/control/user_small.svg'>$userNote</div>
        </div>
		<div id='frameLeft'><ul>" . $menu . "</ul></div>
		<div id='frameRight'><iframe class='iframe' iframeName='主页' src='" . root . "control/adIndex.html?cla=homepage&fun=home&menuType=$userMenu'></iframe></div>
        <div id='appendBox'>" . $this->getUserBox() . "</div>
        <div id='languageBox'>" . self::getLanguage() . "</div>
		" . $this->loadHtml() . $this->menuFourHtml() . $this->js() . warn() . "
		<script>
		initMenu();
		moveMenu()
		$('#language').on('click', function (){
            $('#languageBox').toggle()
		})
        $('#frameLeft').on('mouseenter', 'li[menutwo]', function(event) {
            $('#frameLeft li[menutwo]').removeClass('frameLeftShow')
		    $(this).addClass('frameLeftShow');
            showMenuFour($(this),$(this).attr('menu_one'),$(this).attr('menutwo'))
            autoAdjustPosition($('.menu-four-box'));//有滚动时，自动调整位置
        })
        var menu_con = ''
        // 移出二级菜单和三级菜单区域
        $(document).on('mouseleave', 'li[menutwo], .menu-four-box', function(event) {
            let nextTarget = event.relatedTarget;//移出后的当前元素
            let target = event.target;//移出前的元素
            if (!$(nextTarget).closest('li[menutwo]').is(target) && !$(nextTarget).closest('.menu-four-box').length && !$(nextTarget).is(target) && !$(nextTarget).is('.menu-four-box')) {
                // 移入菜单背景则延迟关闭菜单
                if($(target).closest('.menu-four-box').length && $(nextTarget).is('.menu-four-back')){
                    menu_con = setTimeout(function () {
                        hideMenuFour();
                    }, 300);
                }else{
                    clearTimeout(menu_con);
                    hideMenuFour();
                }
                removeHover();
            }
        });
		// 从菜单背景移回菜单区域，取消定时关闭菜单
		$(document).on('mouseleave', '.menu-four-back', function(event) {
            let nextTarget = event.relatedTarget;//移出后的当前元素
            let target = event.target;//移出前的元素
            if ($(target).is('.menu-four-back') && $(nextTarget).closest('.menu-four-box-content').length) {
                clearTimeout(menu_con);
            }
        });
		// 点击背景关闭菜单
		$(document).on('click', '.menu-four-back,.menu-bridge', function(event) {
            removeHover();
            hideMenuFour();
        });
		$(document).on('click', function(event) {
            // 检查被点击的元素是否是 #languageBox 或其内部元素
            if (!$(event.target).closest('#languageBox').length && !$(event.target).is('#languageBox') && !$(event.target).is('#language') && !$(event.target).closest('#language').length) {
                // 如果不是 #languageBox 或其内部元素，则隐藏 #languageBox
                $('#languageBox').hide(500);
            }
        });
        </script>
		</body>
	</html>";
    }

    /**
     * 第三、四级菜单页面
     * @return string
     */
    public function menuFourHtml()
    {
        return <<<eof
<div class="menu-four-back"></div>
<div class="menu-four-box">
    <div class="menu-flex-box">
        <div class="menu-bridge"></div>
        <div class="menu-four-box-content">
            <div class="arrow-ico"></div>
          <div class="menu-four-box-inner"></div>
        </div>
    </div>
</div>
eof;

    }

    static function getLanguage()
    {
        return selectMultiple([
            'name'   => 'language',
            'title'  => '',
            'value'  => lang,
            'option' => [
                'SC' => '简体中文',
                'TC' => '繁體中文',
                'EN' => 'English',
            ],
            'class'  => 'width150',
            'change' => 'languageToggle',
        ]);
    }

    private function js(): string
    {
        return <<<EOT
<script>
function searchMenu(){
    $("#searchMenuInput").val('');
    $("#searchMenuText").css('display','block');
}
$("#searchMenuInput").bigAutocomplete({
    url:root + 'control/adIndex.html?cla=homepage&fun=menuSearch',
    callback:function(data,e){
        newIframe(data.title,root+data.url,data.menuOneName,data.menuTwoName);
}})
function languageToggle(that){
    const lang = $(that).val()
    $.post(root+'control/adIndex.php?cla=homepage&fun=languageToggle', {lang:lang}, function(res) {
    	if(res.warn === 2){
    		$('#languageBox').hide(700)
            window.location.reload()
    	}else{
            msg(res.warn)
    	}
    },'json')
}
</script>
EOT;
    }

    /**
     * loading
     *
     * @return string
     */
    public function loadHtml(): string
    {
        return <<<EOT
         <div id='loading' style='width: 100%;height: 100%;display: none'>
            <div style="width: 100%;height: 100%;display: grid;place-items: center;">
                 <div class='dibian' style='opacity: 0.1;'></div>
                    <div class="loader loader-1" style="z-index: 999;position: absolute;top: 45%;left: 50%;transform: translate(-50%, -100%);">
                    <div class="loader-outter"></div>
                    <div class="loader-inner"></div>
                 </div>
            </div>
         </div>
EOT;
    }

    public static function isOneDimensionalArray($array)
    {
        if (!is_array($array)) return false; // 首先确保传入的参数是一个数组
        foreach ($array as $value) {
            if (is_array($value)) return false; // 若存在子数组，则不是一维数组
        }
        return true; // 没有发现任何子数组，说明是一维数组
    }

    public static function extractBottomArray($array)
    {
        $result = [];
        foreach ($array as $key => $item) {
            if (is_array($item)) {
                if (self::isOneDimensionalArray($item)) {
                    $result[$key] = self::extractBottomArray($item);
                } else {
                    $result = array_merge($result, self::extractBottomArray($item));
                }
            } else {
                $result[$key] = $item;
            }
        }
        return $result;
    }

    /**
     * 获取左边二级菜单
     *
     * @return string
     */
    public function getframeLeft(): string
    {
        $menu = '';
        foreach ($this->powerAllLang as $menuOneName => $menuOneVal) {
            if (count(array_intersect_key(self::extractBottomArray(array_values($menuOneVal)), $this->controlPower)) > 0) {
                $menu .= "
                    <li title='" . $menuOneName . "' menuOne='" . $menuOneName . "' onclick=\"menuOne(this)\">
                        <img src='" . root . "img/images/triangleRight.png'>
                        " . $menuOneName . "
                    </li>";
                foreach ($menuOneVal as $menuTwoName => $menuTwoValue) {
                    if (count(array_intersect_key(self::extractBottomArray(array_values($menuTwoValue)), $this->controlPower)) > 0) {
                        //子菜单
                        $menu .= "<li style='position:relative;' title='" . $menuTwoName . "' menu_one = '$menuOneName' menuParent='" . $menuOneName . "' menuTwo='" . $menuTwoName . "' ><div>" . $menuTwoName . "</div></li>
";
                    }
                }
            }
        }
        return $menu;
    }

    /**
     * 获取标记数量
     *
     * @param string $type
     * @return int
     */
    public function getMarkNum(string $type): int
    {
        $total = 0;
        switch ($type) {
            case '待办':
                $total = static::total(
                    ['table' => 'backlog', "where" => " `stid`='" . self::$stid . "' AND `workFlow`='待处理' "]
                );
                break;
            case '消息':
                $total = static::total(['table' => 'message', "where" => " `stid`='" . self::$stid . "' AND `see`='否' "]
                );
                break;
            case '合计':
                foreach (['待办', '消息'] as $type) {
                    $total += $this->getMarkNum($type);
                }
                break;
            default:
                break;
        }
        return $total;
    }

    /**
     * 获取会员中心列表
     *
     * @return string
     */
    public function getUserBox(): string
    {
        $avatar  = $this->control['ico'];
        $temp    = '<ul class="userList">';
        $helpUrl = para('helpUrl');
        $array   = [
            [
                'avatar' => root . $avatar,
                'click'  => "newIframe('个人档案', '{$this->root}control/adIndex.html?cla=my&fun=home')",
            ],
            [
                'title' => '我的待办',
                'mark'  => $this->getMarkNum('待办'),
                'click' => "newIframe('我的待办', '{$this->root}control/adIndex.html?cla=backlog&fun=home')",
            ],
            [
                'title' => '我的消息',
                'mark'  => $this->getMarkNum('消息'),
                'click' => "newIframe('我的待办', '{$this->root}control/adIndex.html?cla=message&fun=home')",
            ],
            [
                'title' => '帮助文档',
                'click' => "window.open('" . $helpUrl . "')",
            ],
            [
                'title' => '系统日志',
                'click' => "newIframe('系统日志', '{$this->root}control/adIndex.html?cla=log&fun=home')",
            ],
            [
                'title' => '退出登录',
                'href'  => $this->root . 'control/adIndex.html?cla=login&fun=out',
            ],
        ];
        foreach ($array as $key => $value) {
            $mark  = isset($value['mark']) && $value['mark'] ? '<span class="corner-marks">' . $value['mark'] . '</span>' : '';
            $click = isset($value['click']) && $value['click'] ? 'onclick="' . $value['click'] . '"' : '';
            $href  = isset($value['href']) && $value['href'] ? 'href="' . $value['href'] . '"' : '';
            if ($key == 0) {
                $temp .= '<a ' . $href . '><li class="user-avatar" ' . $click . '><img class="user-avatar-img" src="' . $value['avatar'] . '"><span class="user-avatar-title">' . self::$user['name'] . '</li></a>';
            } else {
                $temp .= '<a ' . $href . '><li ' . $click . '>' . $value['title'] . $mark . '</li></a>';
            }
        }
        $temp .= '</ul>';
        return $temp;
    }

    /**
     * 分转元
     */
    public static function centToYuan($money): float|int
    {
        return $money / self::baseUnit;
    }

    /**
     * 元转分
     */
    public static function yuanToCent($money): float|int
    {
        $money = $money ?: 0;
        return $money * self::baseUnit;
    }

    /**
     * 对比获取一级菜单
     *
     * @return array
     */
    public static function getMenuHandle(): array
    {
        $userKeys = array_keys(self::getUserPower());
        $array    = [];
        $powerAll = $GLOBALS['powerAll'];
        foreach ($powerAll as $oneName => $twoArray) {
            foreach ($twoArray as $threeArray) {
                $data = array_keys($threeArray);
                $res  = array_intersect($data, $userKeys);
                if (count($res) > 0) {
                    $array[] = $oneName;
                    break;
                }
            }
        }
        return $array;
    }

    /**
     * 获取菜单
     *
     * @return string
     */
    public static function getMenu(): string
    {
        $nowMenu = self::$user['menu'] ?? '个人中心';
        $array   = self::getMenuHandle();
        // 计算
        $radix  = 7;
        $col    = ceil(count($array) / $radix);
        $width  = $col * 150 - ($col * 4);
        $height = count($array) > $radix ? $radix * 35 : count($array) * 35;
        $x      = 1;
        $temp   = '<ul class="primaryMenu" style="width:' . $width . 'px;height:' . $height . 'px;">';
        $flag   = true;
        foreach ($array as $key => $value) {
            // 是否标记
            if ($value == $nowMenu) {
                $clipSel = 'clip-selected';
                $liSel   = 'selected';
            } else {
                $clipSel = '';
                $liSel   = '';
            }
            if ($flag) {
                $key  += 1;
                $temp .= '<li data-key=' . $key . ' class="' . $liSel . '"><span>' . $value . '</span><img src="' . root . 'img/control/clip.svg" class="clip ' . $clipSel . '" data-title="' . $value . '"></li>';
            }
            if ($key && ceil($key / $radix) - 1 >= 1) {
                $right = $x * 150 - $x;
                $temp  .= '<hr class="interval-line-right" style="left:' . $right . 'px;height:' . $height . 'px">';
                $x     += 1;
            }
        }
        $temp .= "</ul>";
        return $temp;
    }

    /*返回*/
    public function adIndexHtml()
    {
        if ($this->get('cla') == "login") {
            if (empty($this->warn)) {
                header("location:" . root . "control/adIndex.html");
                exit(0);
            }
            $html = $this->login();
        } elseif ($this->get('cla') == "desktopShortcut") {
            $this->desktopShortcut();
            $html = '';
        } elseif ($this->get('cla') == "auditingFollow") {
            $title = array(
                "staff"         => "员工",
                "adWork"        => "请假",
                "adWorkOut"     => "外出",
                "adWorkSignAdd" => "补卡",
                "adWorkAdd"     => "加班",
                "order"         => "订单",
            );
            $html  = $this->layer(
                array(
                    "title"  => $title[$this->get('fun')] . "审批记录",
                    "height" => 500,
                    "width"  => 1000,
                    "zindex" => 6,
                    "html"   => $this->auditingFollow($this->post('id')),
                )
            );
        } elseif (!empty($this->warn)) {//如果存在登录提示
            /*if (empty($this->get('cla'))) {//如果是框架级刷新，则跳转至登录页
                $_SESSION['warn'] = $this->warn;
                header("location:" . root . "control/adIndex.html?cla=login");
                exit();
            } else {//如果是内页请求，包括异步请求，则返回json数据
                $json['warn'] = $this->warn;
                $html         = json_encode($json, 320);
            }*/
            $_SESSION['warn'] = $this->warn;
            header("location:" . root . "control/adIndex.html?cla=login");
            exit();
        } elseif (empty($this->get('cla'))) {
            $html = $this->frame();//如果get没有类名称，则返回框架信息
        } elseif ($this->get('cla') == "pasWarn") {
            $html = $this->pasWarn();
        } else {
            //定义名称
            $className = $this->get('cla') . "Class";                  //类名称
            $fun       = $this->get('fun');                            //类的方法名称
            $classUrl  = serverRoot . "control/" . $className . ".php";//类文件路径
            //获取类文件
            if (!file_exists($classUrl)) {
                $html = $className . '开发中';
            } elseif (empty($fun)) {
                $html = "类的方法名称为空";
            } elseif (!method_exists(__NAMESPACE__ . '\\' . $className, $fun)) {
                $html = $className . "类中未找到方法" . $fun;
            } else {
                //设置当前消息为已读状态
                $this->messageRead();
                //实例化对象
                $class = new (__NAMESPACE__ . '\\' . $className)();
                //打印结果
                $html = $class->$fun();
            }
        }
        //返回
        return $html;
    }

    public function getToken()
    {
        $tokenKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9";
        $token = static::rGet($tokenKey);
        if($token){
            return ['code'=>true,'msg'=>'成功','data'=>$token];
        }
        //跨域需提交的数据
        $post_data = array(
            "username"=>"cqtxhgqt",
            "password"=>"65f9e9b79eb60c74f6a8a05e2ec3fbb1",
        );
        $resData = $this->send_post("api/Qp_OpenApiMade/login",$post_data);//获取token
        if($resData['code'] !== 1){
            return ['code'=>false,'msg'=>"获取权限失败；失败原因：".$resData['msg'],'data'=>$resData['token']];
        }
        static::rSet($tokenKey,$resData['token']);
        return ['code'=>true,'msg'=>'成功','data'=>$resData['token']];
    }

    /**
     * 请求外部接口
     * @param $url
     * @param $post_data
     * @param string $token
     * @return mixed
     */
    public static function send_post($url, $post_data, string $token=''): mixed
    {
        // 模拟提交数据函数
        $curl = curl_init();
        curl_setopt_array($curl, array(
            CURLOPT_URL => "http://www.qiping123.cn/".$url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_ENCODING => '',
            CURLOPT_MAXREDIRS => 10,
            CURLOPT_TIMEOUT => 0,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_CUSTOMREQUEST => 'POST',
            CURLOPT_POSTFIELDS =>  json_encode($post_data),
            CURLOPT_HTTPHEADER => array(
                'Authorization: Bearer '. $token,// 自定义请求头
                'User-Agent: apifox/1.0.0 (https://www.apifox.cn)',
                'Content-Type: application/json'
            ),
        ));

        $response = curl_exec($curl);
        $response = json_decode($response,true);

        curl_close($curl);
        return $response;

        // 初始化cURL会话
        $ch = curl_init();
        // 设置cURL选项
        curl_setopt($ch, CURLOPT_URL, "http://cqxygs.cn:5002/".$url); // 目标URL
        curl_setopt($ch, CURLOPT_POST, true); // 发送POST请求
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data)); // POST数据
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回响应而不是输出
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        if($token){
            $headers = array(
                'Accept: */*',
                'Content-Type:  application/json',
                'Authorization: Bearer '. $token// 自定义请求头
            );
        }else{
            // 添加自定义请求头
            $headers = array(
                'Content-Type:  application/json',
                'Accept: */*',
            );
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        // 执行cURL会话
        $response = curl_exec($ch);
        $response = json_decode($response,true);
        // 关闭cURL会话
        curl_close($ch);
        // 打印响应内容
        return $response;
    }
}

//实例化对象
$adIndex = new adIndexClass();
if (empty($adIndex->header['Auth']) && strpos($_SERVER['REQUEST_URI'], '/control') !== false) {
    //打印结果
    $response = $adIndex->adIndexHtml();
    if (isset($_SESSION['warn'])) {
        setcookie('warn', $_SESSION['warn']); //接收session中的提示信息
        unset($_SESSION['warn']);
    }
    exit($response);
}
